diff options
Diffstat (limited to 'src/encoding/json/encode.go')
-rw-r--r-- | src/encoding/json/encode.go | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index 6fcea4735f..0371f0a24d 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -1093,7 +1093,22 @@ 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 || sf.Type.Kind() != reflect.Struct) { // unexported + if sf.Anonymous { + t := sf.Type + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + // If embedded, StructField.PkgPath is not a reliable + // indicator of whether the field is exported. + // See https://golang.org/issue/21122 + if !isExported(t.Name()) && t.Kind() != reflect.Struct { + // Ignore embedded fields of unexported non-struct types. + // Do not ignore embedded fields of unexported struct types + // since they may have exported fields. + continue + } + } else if sf.PkgPath != "" { + // Ignore unexported non-embedded fields. continue } tag := sf.Tag.Get("json") @@ -1211,6 +1226,12 @@ func typeFields(t reflect.Type) []field { return fields } +// isExported reports whether the identifier is exported. +func isExported(id string) bool { + r, _ := utf8.DecodeRuneInString(id) + return unicode.IsUpper(r) +} + // dominantField looks through the fields, all of which are known to // have the same name, to find the single field that dominates the // others using Go's embedding rules, modified by the presence of |