-
Notifications
You must be signed in to change notification settings - Fork 18k
encoding/json: resolve struct, map, array, or slice values in interface types #27701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This work extends the behaviour of json.Unmarshal to allow for setting into concrete types embedded in interface{} struct fields. For example, the following JSON object: {"A": {"B": "C"}} Being unmarshaled into the following structure: var t = struct{ A interface{} }{A: struct{ B string }{}} Would have previously resulted in field A being replaced with a map[string]interface{}, disregarding the underlying type given to the interface{} field, i.e.: struct { A interface {} }{A:map[string]interface {}{"B":"C"}} Whereas, by resolving the underlying type of the interface{} field, we are able to set into and return the correct type, i.e.: struct { A interface {} }{A:struct { B string }{B:"C"}} These rules apply also to map types, for JSON objects, and arrays or slices, for JSON arrays. The rules for setting into these fields are exactly the same as those that would apply to the bare types themselves, i.e. attempting to unmarshal into an underlying type that is unable to store the values presented in the JSON input will return a type error. Noted that this is a breaking change for users that relied on having set a concrete type, but handle a map[string]interface{} or []interface{} on the other side. Fixes golang#26946
This PR (HEAD: 0af9368) has been imported to Gerrit for code review. Please visit https://go-review.googlesource.com/c/go/+/135421 to see it. Tip: You can toggle comments from me using the |
Message from Gerrit User 5976: Patch Set 1: Congratulations on opening your first change. Thank you for your contribution! Next steps: Most changes in the Go project go through a few rounds of revision. This can be During May-July and Nov-Jan the Go project is in a code freeze, during which Please don’t reply on this GitHub thread. Visit golang.org/cl/135421. |
Message from Gerrit User 13550: Patch Set 1: It seems to me like this should be discussed on the issue first - it's a non-trivial change in behavior that could lead to subtly breaking existing programs. I realise it hasn't gotten much attention, but that's what the NeedsDecision label is for (as well as proposals, for more complex things). Please don’t reply on this GitHub thread. Visit golang.org/cl/135421. |
Message from Gerrit User 29237: Patch Set 1:
Correct, I've noted as much on the commit message and the initial issue on Github. Even if the modified behaviour here is considered to be "correct", it's gonna be hard to catch in 'go vet', and potentially hard to debug. I mainly did the work here as the code ended up being fairly simple, and as a way of pushing to some sort of consensus. If changing the existing behaviour is considered unacceptable, I could look into clarifying the documentation on json.Unmarshal at the very least. Please don’t reply on this GitHub thread. Visit golang.org/cl/135421. |
Message from Gerrit User 9735: Patch Set 1: I think we should document this instead. The implementation here is indicative of being a set of special-cases, rather than a fix to a more generalized problem. See my comment on the issue. Please don’t reply on this GitHub thread. Visit golang.org/cl/135421. |
This PR is being closed because golang.org/cl/135421 has been abandoned. |
This work extends the behaviour of
json.Unmarshal
to allow for setting into concrete typesembedded in
interface{}
struct fields. For example, the following JSON object:Being unmarshaled into the following structure:
Would have previously resulted in field
A
being replaced with amap[string]interface{}
,disregarding the underlying type given to the
interface{}
field, i.e.:Whereas, by resolving the underlying type of the
interface{}
field, we are able to set into andreturn the correct type, i.e.:
These rules apply also to
map
types, for JSON objects, and arrays or slices, for JSON arrays. Therules for setting into these fields are exactly the same as those that would apply to the bare types
themselves, i.e. attempting to unmarshal into an underlying type that is unable to store the values
presented in the JSON input will return a type error.
Noted that this is a breaking change for users that relied on having set a concrete type, but handle
a
map[string]interface{}
or[]interface{}
on the other side.Fixes #26946