From 6e3f3af4e0f4293f868aa71c4271cab6344d5797 Mon Sep 17 00:00:00 2001 From: Rick Arnold Date: Tue, 22 Jan 2013 17:49:07 -0500 Subject: [PATCH] encoding/json: ignore unexported fields in Unmarshal Go 1.0 behavior was to create an UnmarshalFieldError when a json value name matched an unexported field name. This error will no longer be created and the field will be skipped instead. Fixes #4660. R=adg, rsc, bradfitz CC=golang-dev https://golang.org/cl/7139049 --- src/pkg/encoding/json/decode.go | 10 +--------- src/pkg/encoding/json/decode_test.go | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/pkg/encoding/json/decode.go b/src/pkg/encoding/json/decode.go index eb8c75b24a..6e6815ff13 100644 --- a/src/pkg/encoding/json/decode.go +++ b/src/pkg/encoding/json/decode.go @@ -106,6 +106,7 @@ func (e *UnmarshalTypeError) Error() string { // An UnmarshalFieldError describes a JSON object key that // led to an unexported (and therefore unwritable) struct field. +// (No longer used; kept for compatibility.) type UnmarshalFieldError struct { Key string Type reflect.Type @@ -530,15 +531,6 @@ func (d *decodeState) object(v reflect.Value) { } subv = subv.Field(i) } - } else { - // To give a good error, a quick scan for unexported fields in top level. - st := v.Type() - for i := 0; i < st.NumField(); i++ { - f := st.Field(i) - if f.PkgPath != "" && strings.EqualFold(f.Name, key) { - d.saveError(&UnmarshalFieldError{key, st, f}) - } - } } } diff --git a/src/pkg/encoding/json/decode_test.go b/src/pkg/encoding/json/decode_test.go index 4c75f19f4a..97f2a41eb7 100644 --- a/src/pkg/encoding/json/decode_test.go +++ b/src/pkg/encoding/json/decode_test.go @@ -199,7 +199,7 @@ var unmarshalTests = []unmarshalTest{ {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"}, {in: "null", ptr: new(interface{}), out: nil}, {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf("")}}, - {in: `{"x": 1}`, ptr: new(tx), out: tx{}, err: &UnmarshalFieldError{"x", txType, txType.Field(0)}}, + {in: `{"x": 1}`, ptr: new(tx), out: tx{}}, {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}}, {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true}, {in: `{"k1":1,"k2":"s","k3":[1,2.0,3e-3],"k4":{"kk1":"s","kk2":2}}`, ptr: new(interface{}), out: ifaceNumAsFloat64}, @@ -1064,3 +1064,25 @@ func TestUnmarshalTypeError(t *testing.T) { } } } + +// Test handling of unexported fields that should be ignored. +// Issue 4660 +type unexportedFields struct { + Name string + m map[string]interface{} `json:"-"` + m2 map[string]interface{} `json:"abcd"` +} + +func TestUnmarshalUnexported(t *testing.T) { + input := `{"Name": "Bob", "m": {"x": 123}, "m2": {"y": 456}, "abcd": {"z": 789}}` + want := &unexportedFields{Name: "Bob"} + + out := &unexportedFields{} + err := Unmarshal([]byte(input), out) + if err != nil { + t.Errorf("got error %v, expected nil", err) + } + if !reflect.DeepEqual(out, want) { + t.Errorf("got %q, want %q", out, want) + } +} -- 2.48.1