diff options
| author | Joe Tsai <joetsai@digital-static.net> | 2026-02-02 17:52:37 -0800 |
|---|---|---|
| committer | Joseph Tsai <joetsai@digital-static.net> | 2026-02-12 16:09:06 -0800 |
| commit | c9cbeb0a1b08a9830a3d2d4abe0c2108e52f7647 (patch) | |
| tree | f52aba650a85b15a0a009df469e37c4c4ad76b13 /src/encoding/json/v2/fields.go | |
| parent | 92c7fcf137848ad74f88f75fc21bcb159eb08104 (diff) | |
| download | go-c9cbeb0a1b08a9830a3d2d4abe0c2108e52f7647.tar.xz | |
encoding/json/v2: remove `unknown` tag option and DiscardUnknownMembers
WARNING: This commit contains breaking changes
for those already using GOEXPERIMENT=jsonv2.
This removes support for the `unknown` tag option and
the DiscardUnknownMembers marshal option.
The `unknown` tag option semantics are a bit too subtle
even for experienced Go programmers to understand.
Remove support for it. The exact same feature (or something similar)
can be added back into a future release of json/v2.
We already support the `inline` tag option,
which can handle most cases of what someone might want to do
with unknown fields (such as preserve them).
Fixes #77271
Updates #76444
Change-Id: I875952f0755e58aac4c571869b2cdb56e75cfda9
Reviewed-on: https://go-review.googlesource.com/c/go/+/741320
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/encoding/json/v2/fields.go')
| -rw-r--r-- | src/encoding/json/v2/fields.go | 26 |
1 files changed, 5 insertions, 21 deletions
diff --git a/src/encoding/json/v2/fields.go b/src/encoding/json/v2/fields.go index 4a02be7327..5c560ec5d5 100644 --- a/src/encoding/json/v2/fields.go +++ b/src/encoding/json/v2/fields.go @@ -129,25 +129,16 @@ func makeStructFields(root reflect.Type) (fs structFields, serr *SemanticError) f.inline = true // implied by use of Go embedding without an explicit name } } - if f.inline || f.unknown { + if f.inline { // Handle an inlined field that serializes to/from // zero or more JSON object members. - switch f.fieldOptions { - case fieldOptions{name: f.name, quotedName: f.quotedName, inline: true}: - case fieldOptions{name: f.name, quotedName: f.quotedName, unknown: true}: - case fieldOptions{name: f.name, quotedName: f.quotedName, inline: true, unknown: true}: - serr = orErrorf(serr, t, "Go struct field %s cannot have both `inline` and `unknown` specified", sf.Name) - f.inline = false // let `unknown` take precedence - default: - serr = orErrorf(serr, t, "Go struct field %s cannot have any options other than `inline` or `unknown` specified", sf.Name) + if f.fieldOptions != (fieldOptions{name: f.name, quotedName: f.quotedName, inline: true}) { + serr = orErrorf(serr, t, "Go struct field %s cannot have any options other than `inline` specified", sf.Name) if f.hasName { continue // invalid inlined field; treat as ignored } - f.fieldOptions = fieldOptions{name: f.name, quotedName: f.quotedName, inline: f.inline, unknown: f.unknown} - if f.inline && f.unknown { - f.inline = false // let `unknown` take precedence - } + f.fieldOptions = fieldOptions{name: f.name, quotedName: f.quotedName, inline: f.inline} } // Reject any types with custom serialization otherwise @@ -160,10 +151,6 @@ func makeStructFields(root reflect.Type) (fs structFields, serr *SemanticError) // Handle an inlined field that serializes to/from // a finite number of JSON object members backed by a Go struct. if tf.Kind() == reflect.Struct { - if f.unknown { - serr = orErrorf(serr, t, "inlined Go struct field %s of type %s with `unknown` tag must be a Go map of string key or a jsontext.Value", sf.Name, tf) - continue // invalid inlined field; treat as ignored - } if qe.visitChildren { queue = append(queue, queueEntry{tf, f.index, !seen[tf]}) } @@ -392,7 +379,6 @@ type fieldOptions struct { nameNeedEscape bool casing int8 // either 0, caseIgnore, or caseStrict inline bool - unknown bool omitzero bool omitempty bool string bool @@ -526,8 +512,6 @@ func parseFieldOptions(sf reflect.StructField) (out fieldOptions, ignored bool, } case "inline": out.inline = true - case "unknown": - out.unknown = true case "omitzero": out.omitzero = true case "omitempty": @@ -553,7 +537,7 @@ func parseFieldOptions(sf reflect.StructField) (out fieldOptions, ignored bool, // This catches invalid mutants such as "omitEmpty" or "omit_empty". normOpt := strings.ReplaceAll(strings.ToLower(opt), "_", "") switch normOpt { - case "case", "inline", "unknown", "omitzero", "omitempty", "string", "format": + case "case", "inline", "omitzero", "omitempty", "string", "format": err = cmp.Or(err, fmt.Errorf("Go struct field %s has invalid appearance of `%s` tag option; specify `%s` instead", sf.Name, opt, normOpt)) } |
