|
|
|
@ -70,15 +70,15 @@ func UnmarshalKey(m map[string]interface{}, v interface{}) error {
|
|
|
|
|
|
|
|
|
|
// Unmarshal unmarshals m into v.
|
|
|
|
|
func (u *Unmarshaler) Unmarshal(m map[string]interface{}, v interface{}) error {
|
|
|
|
|
return u.UnmarshalValuer(MapValuer(m), v)
|
|
|
|
|
return u.UnmarshalValuer(mapValuer(m), v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// UnmarshalValuer unmarshals m into v.
|
|
|
|
|
func (u *Unmarshaler) UnmarshalValuer(m Valuer, v interface{}) error {
|
|
|
|
|
return u.unmarshalWithFullName(m, v, "")
|
|
|
|
|
return u.unmarshalWithFullName(simpleValuer{current: m}, v, "")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Unmarshaler) unmarshalWithFullName(m Valuer, v interface{}, fullName string) error {
|
|
|
|
|
func (u *Unmarshaler) unmarshalWithFullName(m valuerWithParent, v interface{}, fullName string) error {
|
|
|
|
|
rv := reflect.ValueOf(v)
|
|
|
|
|
if err := ValidatePtr(&rv); err != nil {
|
|
|
|
|
return err
|
|
|
|
@ -102,7 +102,7 @@ func (u *Unmarshaler) unmarshalWithFullName(m Valuer, v interface{}, fullName st
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Unmarshaler) processAnonymousField(field reflect.StructField, value reflect.Value,
|
|
|
|
|
m Valuer, fullName string) error {
|
|
|
|
|
m valuerWithParent, fullName string) error {
|
|
|
|
|
key, options, err := u.parseOptionsWithContext(field, m, fullName)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
@ -120,7 +120,7 @@ func (u *Unmarshaler) processAnonymousField(field reflect.StructField, value ref
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Unmarshaler) processAnonymousFieldOptional(field reflect.StructField, value reflect.Value,
|
|
|
|
|
key string, m Valuer, fullName string) error {
|
|
|
|
|
key string, m valuerWithParent, fullName string) error {
|
|
|
|
|
var filled bool
|
|
|
|
|
var required int
|
|
|
|
|
var requiredFilled int
|
|
|
|
@ -161,7 +161,7 @@ func (u *Unmarshaler) processAnonymousFieldOptional(field reflect.StructField, v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Unmarshaler) processAnonymousFieldRequired(field reflect.StructField, value reflect.Value,
|
|
|
|
|
m Valuer, fullName string) error {
|
|
|
|
|
m valuerWithParent, fullName string) error {
|
|
|
|
|
maybeNewValue(field, value)
|
|
|
|
|
fieldType := Deref(field.Type)
|
|
|
|
|
indirectValue := reflect.Indirect(value)
|
|
|
|
@ -175,8 +175,8 @@ func (u *Unmarshaler) processAnonymousFieldRequired(field reflect.StructField, v
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Unmarshaler) processField(field reflect.StructField, value reflect.Value, m Valuer,
|
|
|
|
|
fullName string) error {
|
|
|
|
|
func (u *Unmarshaler) processField(field reflect.StructField, value reflect.Value,
|
|
|
|
|
m valuerWithParent, fullName string) error {
|
|
|
|
|
if usingDifferentKeys(u.key, field) {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
@ -189,15 +189,23 @@ func (u *Unmarshaler) processField(field reflect.StructField, value reflect.Valu
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Unmarshaler) processFieldNotFromString(field reflect.StructField, value reflect.Value,
|
|
|
|
|
mapValue interface{}, opts *fieldOptionsWithContext, fullName string) error {
|
|
|
|
|
vp valueWithParent, opts *fieldOptionsWithContext, fullName string) error {
|
|
|
|
|
fieldType := field.Type
|
|
|
|
|
derefedFieldType := Deref(fieldType)
|
|
|
|
|
typeKind := derefedFieldType.Kind()
|
|
|
|
|
valueKind := reflect.TypeOf(mapValue).Kind()
|
|
|
|
|
valueKind := reflect.TypeOf(vp.value).Kind()
|
|
|
|
|
mapValue := vp.value
|
|
|
|
|
|
|
|
|
|
switch {
|
|
|
|
|
case valueKind == reflect.Map && typeKind == reflect.Struct:
|
|
|
|
|
return u.processFieldStruct(field, value, mapValue, fullName)
|
|
|
|
|
if mv, ok := mapValue.(map[string]interface{}); ok {
|
|
|
|
|
return u.processFieldStruct(field, value, &simpleValuer{
|
|
|
|
|
current: mapValuer(mv),
|
|
|
|
|
parent: vp.parent,
|
|
|
|
|
}, fullName)
|
|
|
|
|
} else {
|
|
|
|
|
return errTypeMismatch
|
|
|
|
|
}
|
|
|
|
|
case valueKind == reflect.Map && typeKind == reflect.Map:
|
|
|
|
|
return u.fillMap(field, value, mapValue)
|
|
|
|
|
case valueKind == reflect.String && typeKind == reflect.Map:
|
|
|
|
@ -292,18 +300,7 @@ func (u *Unmarshaler) processFieldPrimitiveWithJSONNumber(field reflect.StructFi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Unmarshaler) processFieldStruct(field reflect.StructField, value reflect.Value,
|
|
|
|
|
mapValue interface{}, fullName string) error {
|
|
|
|
|
convertedValue, ok := mapValue.(map[string]interface{})
|
|
|
|
|
if !ok {
|
|
|
|
|
valueKind := reflect.TypeOf(mapValue).Kind()
|
|
|
|
|
return fmt.Errorf("error: field: %s, expect map[string]interface{}, actual %v", fullName, valueKind)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return u.processFieldStructWithMap(field, value, MapValuer(convertedValue), fullName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Unmarshaler) processFieldStructWithMap(field reflect.StructField, value reflect.Value,
|
|
|
|
|
m Valuer, fullName string) error {
|
|
|
|
|
m valuerWithParent, fullName string) error {
|
|
|
|
|
if field.Type.Kind() == reflect.Ptr {
|
|
|
|
|
baseType := Deref(field.Type)
|
|
|
|
|
target := reflect.New(baseType).Elem()
|
|
|
|
@ -342,7 +339,7 @@ func (u *Unmarshaler) processFieldTextUnmarshaler(field reflect.StructField, val
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Unmarshaler) processNamedField(field reflect.StructField, value reflect.Value,
|
|
|
|
|
m Valuer, fullName string) error {
|
|
|
|
|
m valuerWithParent, fullName string) error {
|
|
|
|
|
key, opts, err := u.parseOptionsWithContext(field, m, fullName)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
@ -353,16 +350,22 @@ func (u *Unmarshaler) processNamedField(field reflect.StructField, value reflect
|
|
|
|
|
if u.opts.canonicalKey != nil {
|
|
|
|
|
canonicalKey = u.opts.canonicalKey(key)
|
|
|
|
|
}
|
|
|
|
|
mapValue, hasValue := getValue(m, canonicalKey)
|
|
|
|
|
if hasValue {
|
|
|
|
|
return u.processNamedFieldWithValue(field, value, mapValue, key, opts, fullName)
|
|
|
|
|
|
|
|
|
|
valuer := createValuer(m, opts)
|
|
|
|
|
mapValue, hasValue := getValue(valuer, canonicalKey)
|
|
|
|
|
if !hasValue {
|
|
|
|
|
return u.processNamedFieldWithoutValue(field, value, opts, fullName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return u.processNamedFieldWithoutValue(field, value, opts, fullName)
|
|
|
|
|
return u.processNamedFieldWithValue(field, value, valueWithParent{
|
|
|
|
|
value: mapValue,
|
|
|
|
|
parent: valuer,
|
|
|
|
|
}, key, opts, fullName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (u *Unmarshaler) processNamedFieldWithValue(field reflect.StructField, value reflect.Value,
|
|
|
|
|
mapValue interface{}, key string, opts *fieldOptionsWithContext, fullName string) error {
|
|
|
|
|
vp valueWithParent, key string, opts *fieldOptionsWithContext, fullName string) error {
|
|
|
|
|
mapValue := vp.value
|
|
|
|
|
if mapValue == nil {
|
|
|
|
|
if opts.optional() {
|
|
|
|
|
return nil
|
|
|
|
@ -384,7 +387,7 @@ func (u *Unmarshaler) processNamedFieldWithValue(field reflect.StructField, valu
|
|
|
|
|
fieldKind := Deref(field.Type).Kind()
|
|
|
|
|
switch fieldKind {
|
|
|
|
|
case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct:
|
|
|
|
|
return u.processFieldNotFromString(field, value, mapValue, opts, fullName)
|
|
|
|
|
return u.processFieldNotFromString(field, value, vp, opts, fullName)
|
|
|
|
|
default:
|
|
|
|
|
if u.opts.fromString || opts.fromString() {
|
|
|
|
|
valueKind := reflect.TypeOf(mapValue).Kind()
|
|
|
|
@ -403,7 +406,7 @@ func (u *Unmarshaler) processNamedFieldWithValue(field reflect.StructField, valu
|
|
|
|
|
return fillPrimitive(field.Type, value, mapValue, opts, fullName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return u.processFieldNotFromString(field, value, mapValue, opts, fullName)
|
|
|
|
|
return u.processFieldNotFromString(field, value, vp, opts, fullName)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -431,7 +434,9 @@ func (u *Unmarshaler) processNamedFieldWithoutValue(field reflect.StructField, v
|
|
|
|
|
switch fieldKind {
|
|
|
|
|
case reflect.Array, reflect.Map, reflect.Slice:
|
|
|
|
|
if !opts.optional() {
|
|
|
|
|
return u.processFieldNotFromString(field, value, emptyMap, opts, fullName)
|
|
|
|
|
return u.processFieldNotFromString(field, value, valueWithParent{
|
|
|
|
|
value: emptyMap,
|
|
|
|
|
}, opts, fullName)
|
|
|
|
|
}
|
|
|
|
|
case reflect.Struct:
|
|
|
|
|
if !opts.optional() {
|
|
|
|
@ -439,10 +444,14 @@ func (u *Unmarshaler) processNamedFieldWithoutValue(field reflect.StructField, v
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if required {
|
|
|
|
|
return fmt.Errorf("%q is not set", fullName)
|
|
|
|
|
}
|
|
|
|
|
return u.processFieldNotFromString(field, value, emptyMap, opts, fullName)
|
|
|
|
|
|
|
|
|
|
return u.processFieldNotFromString(field, value, valueWithParent{
|
|
|
|
|
value: emptyMap,
|
|
|
|
|
}, opts, fullName)
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
if !opts.optional() {
|
|
|
|
@ -738,6 +747,20 @@ func WithCanonicalKeyFunc(f func(string) string) UnmarshalOption {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func createValuer(v valuerWithParent, opts *fieldOptionsWithContext) valuerWithParent {
|
|
|
|
|
if opts.inherit() {
|
|
|
|
|
return recursiveValuer{
|
|
|
|
|
current: v,
|
|
|
|
|
parent: v.Parent(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return simpleValuer{
|
|
|
|
|
current: v,
|
|
|
|
|
parent: v.Parent(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func fillDurationValue(fieldKind reflect.Kind, value reflect.Value, dur string) error {
|
|
|
|
|
d, err := time.ParseDuration(dur)
|
|
|
|
|
if err != nil {
|
|
|
|
@ -805,26 +828,30 @@ func fillWithSameType(field reflect.StructField, value reflect.Value, mapValue i
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// getValue gets the value for the specific key, the key can be in the format of parentKey.childKey
|
|
|
|
|
func getValue(m Valuer, key string) (interface{}, bool) {
|
|
|
|
|
func getValue(m valuerWithParent, key string) (interface{}, bool) {
|
|
|
|
|
keys := readKeys(key)
|
|
|
|
|
return getValueWithChainedKeys(m, keys)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getValueWithChainedKeys(m Valuer, keys []string) (interface{}, bool) {
|
|
|
|
|
if len(keys) == 1 {
|
|
|
|
|
func getValueWithChainedKeys(m valuerWithParent, keys []string) (interface{}, bool) {
|
|
|
|
|
switch len(keys) {
|
|
|
|
|
case 0:
|
|
|
|
|
return nil, false
|
|
|
|
|
case 1:
|
|
|
|
|
v, ok := m.Value(keys[0])
|
|
|
|
|
return v, ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(keys) > 1 {
|
|
|
|
|
default:
|
|
|
|
|
if v, ok := m.Value(keys[0]); ok {
|
|
|
|
|
if nextm, ok := v.(map[string]interface{}); ok {
|
|
|
|
|
return getValueWithChainedKeys(MapValuer(nextm), keys[1:])
|
|
|
|
|
return getValueWithChainedKeys(recursiveValuer{
|
|
|
|
|
current: mapValuer(nextm),
|
|
|
|
|
parent: m,
|
|
|
|
|
}, keys[1:])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil, false
|
|
|
|
|
return nil, false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func join(elem ...string) string {
|
|
|
|
|