aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/json/encode.go
diff options
context:
space:
mode:
authorJoe Tsai <joetsai@digital-static.net>2017-07-21 16:53:54 -0700
committerJoe Tsai <joetsai@google.com>2017-07-22 01:29:58 +0000
commitb81735924936291303559fd71dabaa1aa88f57c5 (patch)
treef429ab3c9ed7612f1781bc1305635cb622230904 /src/encoding/json/encode.go
parent5f7a03e148b9a37f2c61f7d428abc6b360897a0c (diff)
downloadgo-b81735924936291303559fd71dabaa1aa88f57c5.tar.xz
encoding/json: ignore embedded fields of pointers to unexported non-structs
https://golang.org/cl/33773 fixes the JSON marshaler to avoid serializing embedded fields on unexported types of non-struct types. However, Go allows embedding pointer to types, so the check for whether the field is a non-struct type must first dereference the pointer to get at the underlying type. Furthermore, due to a edge-case in the behavior of StructField.PkgPath not being a reliable indicator of whether the field is unexported (see #21122), we use our own logic to determine whether the field is exported or not. The logic in this CL may be simplified depending on what happens in #21122. Fixes #21121 Updates #21122 Change-Id: I8dfd1cdfac8a87950df294a566fb96dfd04fd749 Reviewed-on: https://go-review.googlesource.com/50711 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/encoding/json/encode.go')
-rw-r--r--src/encoding/json/encode.go23
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