util.go
func decodeToObjOrFieldWithTag(buf []byte, obj interface{}, tagName string, defaultObj interface{}) error {
	// reflect values
	objValElem := reflect.ValueOf(obj).Elem()
	defaultObjValElem := reflect.ValueOf(defaultObj).Elem()

	// first check type, if same type, then set
	if objValElem.Type() == defaultObjValElem.Type() {
		objValElem.Set(defaultObjValElem)
		return nil
	}

	// get field with specified jwt tagName (if any)
	fieldVal := getFieldWithTag(obj, tagName)
	if fieldVal != nil {
		// check field type and defaultObj type, if same, set
		if fieldVal.Type() == defaultObjValElem.Type() {
			fieldVal.Set(defaultObjValElem)
			return nil
		}

		// otherwise, assign obj address of field
		obj = fieldVal.Addr().Interface()
	}

	// decode json
	d := json.NewDecoder(bytes.NewBuffer(buf))
	d.UseNumber()
	return d.Decode(obj)
}
func decodeToObjOrFieldWithTag(buf []byte, obj interface{}, tagName string, defaultObj interface{}) error {
	// reflect values
	objValElem := reflect.ValueOf(obj).Elem()
	defaultObjValElem := reflect.ValueOf(defaultObj).Elem()

	// first check type, if same type, then set
	if objValElem.Type() == defaultObjValElem.Type() {
		objValElem.Set(defaultObjValElem)
		return nil
	}

	// get field with specified jwt tagName (if any)
	fieldVal := getFieldWithTag(obj, tagName)
	if fieldVal != nil {
		// check field type and defaultObj type, if same, set
		if fieldVal.Type() == defaultObjValElem.Type() {
			fieldVal.Set(defaultObjValElem)
			return nil
		}

		// otherwise, assign obj address of field
		obj = fieldVal.Addr().Interface()
	}

	// decode json
	d := json.NewDecoder(bytes.NewBuffer(buf))
	d.UseNumber()
	return d.Decode(obj)
}
// decodeToObjOrFieldWithTag decodes the buf into obj's field having the
// specified jwt tagName. If the provided obj's has the same type as
// defaultObj, then the obj is set to the defaultObj, otherwise an attempt is
// made to json.Decode the buf into obj.