Skip to content
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

encoding/json: calls UnmarshalJSON with a nil receiver on anonymous fields #17877

Closed
epelc opened this issue Nov 10, 2016 · 3 comments

Comments

Projects
None yet
6 participants
@epelc
Copy link

commented Nov 10, 2016

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.7.1 darwin/amd64

What operating system and processor architecture are you using (go env)?

GOHOSTARCH="amd64"
GOHOSTOS="darwin"

What did you do?

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

Custom UnmarshalJSON methods do not properly update an anonymous field on an outer struct when it is unmarshaled.
https://play.golang.org/p/wkQhDFiO82

It works correctly if the outer struct's field is not anonymous. If the field is anonymous it only works if you initialize it firstx.SomeType = &SomeType{}.
https://play.golang.org/p/DYuygZrLgk

edit - also note this works fine if you do not have custom UnmarshalJSON https://play.golang.org/p/2HhHJ19wpQ

What did you expect to see?

The anonymous field should be set and have Price: 99 like in the second example.

What did you see instead?

The anonymous field is nil

I'm not sure if this counts as a bug or what underlying issue is causing it. But it is very confusing from a user's perspective and it seems like it might be a compiler issue(maybe?).

@quentinmit quentinmit added this to the Go1.8Maybe milestone Nov 16, 2016

@quentinmit

This comment has been minimized.

Copy link
Contributor

commented Nov 16, 2016

I'm not sure if this is just a documentation bug or if we actually want to create a SomeType instance. In general nil receivers are fine, but I agree it doesn't make sense for UnmarshalJSON to be given a nil receiver.

/cc @rsc

@quentinmit quentinmit changed the title encoding/json: Doesn't Unmarshal anonymous field with custom unmarshaler encoding/json: calls UnmarshalJSON with a nil receiver on anonymous fields Nov 16, 2016

@bradfitz bradfitz modified the milestones: Go1.9, Go1.8Maybe Dec 3, 2016

@shantuo

This comment has been minimized.

Copy link
Contributor

commented Feb 9, 2017

My understanding is that this is working as intended. In the first case, Outer is a Marshaler, so Unmarshal will call its custom UnmarshalJSON on it directly. While in other cases, Outer is not a Marshaler. The default behavior for Unmarshal is documented as:

If the pointer is nil, Unmarshal allocates a new value for it to point to.

@rsc

This comment has been minimized.

Copy link
Contributor

commented Feb 9, 2017

Yes, @shantuo is right. From the json package's point of view, it allocates an Outer, sees that Outer has an UnmarshalJSON method (due to the embedding), and invokes Outer's UnmarshalJSON method. The raison d'être of UnmarshalJSON is to stop the usual processing, and in this case, that means not looking inside Outer at all. The json package cannot be responsible for allocating the inner struct.

Other ways to write this code include embedding a struct instead of a pointer-to-struct.

@rsc rsc closed this Feb 9, 2017

@golang golang locked and limited conversation to collaborators Feb 9, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.