From: Rick Arnold Date: Tue, 22 Jan 2013 22:49:07 +0000 (-0500) Subject: encoding/json: ignore unexported fields in Unmarshal X-Git-Tag: go1.1rc2~1315 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=6e3f3af4e0f4293f868aa71c4271cab6344d5797;p=gostls13.git 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 --- 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) + } +}