]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json: ignore unexported fields in Unmarshal
authorRick Arnold <rickarnoldjr@gmail.com>
Tue, 22 Jan 2013 22:49:07 +0000 (17:49 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 22 Jan 2013 22:49:07 +0000 (17:49 -0500)
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
src/pkg/encoding/json/decode_test.go

index eb8c75b24ad4f1411802a811f3626f1321c86bfb..6e6815ff13185c7ea1f40ba4173be32d56e2c4ee 100644 (file)
@@ -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})
-                                       }
-                               }
                        }
                }
 
index 4c75f19f4aa5e5805a1576e568874a6a02c30ab9..97f2a41eb767db439705134f0ad5fa53c1086c3f 100644 (file)
@@ -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)
+       }
+}