Skip to content

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

Closed
wants to merge 1 commit into from

Conversation

deuill
Copy link

@deuill deuill commented Sep 16, 2018

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 #26946

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
@googlebot googlebot added the cla: yes Used by googlebot to label PRs as having a valid CLA. The text of this label should not change. label Sep 16, 2018
@gopherbot
Copy link
Contributor

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 comments slash command (e.g. /comments off)
See the Wiki page for more info

@gopherbot
Copy link
Contributor

Message from Gerrit User 5976:

Patch Set 1:

Congratulations on opening your first change. Thank you for your contribution!

Next steps:
Within the next week or so, a maintainer will review your change and provide
feedback. See https://golang.org/doc/contribute.html#review for more info and
tips to get your patch through code review.

Most changes in the Go project go through a few rounds of revision. This can be
surprising to people new to the project. The careful, iterative review process
is our way of helping mentor contributors and ensuring that their contributions
have a lasting impact.

During May-July and Nov-Jan the Go project is in a code freeze, during which
little code gets reviewed or merged. If a reviewer responds with a comment like
R=go1.11, it means that this CL will be reviewed as part of the next development
cycle. See https://golang.org/s/release for more details.


Please don’t reply on this GitHub thread. Visit golang.org/cl/135421.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

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.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

Message from Gerrit User 29237:

Patch Set 1:

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).

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.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

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.
After addressing review feedback, remember to publish your drafts!

@gopherbot
Copy link
Contributor

This PR is being closed because golang.org/cl/135421 has been abandoned.

@gopherbot gopherbot closed this Oct 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Used by googlebot to label PRs as having a valid CLA. The text of this label should not change.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants