]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json: don't marshal unexported embedded fields of non struct type
authorthoeni <thoeni@gmail.com>
Thu, 1 Dec 2016 21:57:39 +0000 (21:57 +0000)
committerRuss Cox <rsc@golang.org>
Wed, 14 Jun 2017 19:01:08 +0000 (19:01 +0000)
Marshal must process unexported embedded fields of struct type,
looking for exported fields in those structs. However, it must
not process unexported embedded fields of non-struct type.

For example, consider:

    type t1 struct {
        X int
    }
    type t2 int
    type T struct {
        t1
        t2
    }

When considering T, Marshal must process t1 to find t1.X.
Marshal must not process t2, but it was. Fix that.

Fixes #18009

Change-Id: I62ba0b65ba30fd927990e101a26405a9998787a3
Reviewed-on: https://go-review.googlesource.com/33773
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/encoding/json/encode.go
src/encoding/json/encode_test.go

index 4a5ab9c0166c21ef94f0cb19d7b17740bba59af2..6fcea4735f931315425f2078b55faa2e2e65d8dd 100644 (file)
@@ -1093,7 +1093,7 @@ func typeFields(t reflect.Type) []field {
                        // Scan f.typ for fields to include.
                        for i := 0; i < f.typ.NumField(); i++ {
                                sf := f.typ.Field(i)
-                               if sf.PkgPath != "" && !sf.Anonymous { // unexported
+                               if sf.PkgPath != "" && (!sf.Anonymous || sf.Type.Kind() != reflect.Struct) { // unexported
                                        continue
                                }
                                tag := sf.Tag.Get("json")
index 6d574cfc47bd833f056c48a502bca835a7d283f0..d5f5f0a691d3587fe965fa3d18c9ff7284cebe08 100644 (file)
@@ -273,6 +273,59 @@ func TestAnonymousNonstruct(t *testing.T) {
        }
 }
 
+type unexportedIntType int
+
+type MyStructWithUnexportedIntType struct {
+       unexportedIntType
+}
+
+func TestAnonymousNonstructWithUnexportedType(t *testing.T) {
+       a := MyStructWithUnexportedIntType{11}
+       const want = `{}`
+
+       b, err := Marshal(a)
+       if err != nil {
+               t.Fatalf("Marshal: %v", err)
+       }
+       if got := string(b); got != want {
+               t.Errorf("got %q, want %q", got, want)
+       }
+}
+
+type MyStructContainingUnexportedStruct struct {
+       unexportedStructType1
+       unexportedIntType
+}
+
+type unexportedStructType1 struct {
+       ExportedIntType1
+       unexportedIntType
+       unexportedStructType2
+}
+
+type unexportedStructType2 struct {
+       ExportedIntType2
+       unexportedIntType
+}
+
+type ExportedIntType1 int
+type ExportedIntType2 int
+
+func TestUnexportedAnonymousStructWithExportedType(t *testing.T) {
+       s2 := unexportedStructType2{3, 4}
+       s1 := unexportedStructType1{1, 2, s2}
+       a := MyStructContainingUnexportedStruct{s1, 6}
+       const want = `{"ExportedIntType1":1,"ExportedIntType2":3}`
+
+       b, err := Marshal(a)
+       if err != nil {
+               t.Fatalf("Marshal: %v", err)
+       }
+       if got := string(b); got != want {
+               t.Errorf("got %q, want %q", got, want)
+       }
+}
+
 type BugA struct {
        S string
 }