diff --git a/unmarshaler.go b/unmarshaler.go index 2219f704..0f81f5cd 100644 --- a/unmarshaler.go +++ b/unmarshaler.go @@ -230,15 +230,6 @@ func (d *decoder) fromParser(root reflect.Value) error { return d.p.Error() } -/* -Rules for the unmarshal code: - -- The stack is used to keep track of which values need to be set where. -- handle* functions <=> switch on a given ast.Kind. -- unmarshalX* functions need to unmarshal a node of kind X. -- An "object" is either a struct or a map. -*/ - func (d *decoder) handleRootExpression(expr *ast.Node, v reflect.Value) error { var x reflect.Value var err error @@ -400,6 +391,46 @@ func (d *decoder) handleArrayTableCollection(key ast.Iterator, v reflect.Value) return d.handleArrayTable(key, v) } +func (d *decoder) handleKeyPartMapStringInterface(key ast.Iterator, m map[string]interface{}, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) { + newMap := false + + k := string(key.Node().Data) + if m == nil { + newMap = true + m = make(map[string]interface{}, 8) + } + + v, ok := m[k] + set := false + + if !ok || v == nil { + set = true + v = makeFn().Interface() + } + + mv := reflect.ValueOf(v) + + x, err := nextFn(key, mv) + if err != nil { + return reflect.Value{}, err + } + + if x.IsValid() { + mv = x + set = true + } + + if set { + m[k] = mv.Interface() + } + + if newMap { + return reflect.ValueOf(m), nil + } + + return reflect.Value{}, nil +} + func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) { var rv reflect.Value @@ -416,6 +447,11 @@ func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handle case reflect.Map: vt := v.Type() + if vt == mapStringInterfaceType { + m := v.Interface().(map[string]interface{}) + return d.handleKeyPartMapStringInterface(key, m, nextFn, makeFn) + } + // Create the key for the map element. Convert to key type. mk := reflect.ValueOf(string(key.Node().Data)).Convert(vt.Key())