aboutsummaryrefslogtreecommitdiff
path: root/src/encoding/json/v2/fields.go
diff options
context:
space:
mode:
authorJoe Tsai <joetsai@digital-static.net>2026-02-02 17:52:37 -0800
committerJoseph Tsai <joetsai@digital-static.net>2026-02-12 16:09:06 -0800
commitc9cbeb0a1b08a9830a3d2d4abe0c2108e52f7647 (patch)
treef52aba650a85b15a0a009df469e37c4c4ad76b13 /src/encoding/json/v2/fields.go
parent92c7fcf137848ad74f88f75fc21bcb159eb08104 (diff)
downloadgo-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.go26
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))
}