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: Unexpected marshal behavior #21903

Closed
alexandrevicenzi opened this issue Sep 15, 2017 · 5 comments
Closed

encoding/json: Unexpected marshal behavior #21903

alexandrevicenzi opened this issue Sep 15, 2017 · 5 comments
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.

Comments

@alexandrevicenzi
Copy link

I created a custom MarshalJSON for my struct and it outputs the wrong struct if I have customs MarshalJSON nested in my struct.

I'm trying to understand why it doesn't work as expected. I know that there are some limitations with type redefinition but it works well if I don't nest any struct with a custom MarshalJSON.

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

1.8

Does this issue reproduce with the latest release?

Yes

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

Linux

What did you do?

https://play.golang.org/p/Mp1ot20ILA

This example is just to be able to reproduce the problem. I know it doesn't make any sense the custom Copy type, but in a real problem, I would extend Copy type by adding custom fields.

What did you expect to see?

{"value":"A"}
{"value":"B","A":{"value":"A"}}
{"value":"C","A":{"value":"A"},"B":{"value":"B","A":{"value":"A"}}}

or at least

{"value":"A"}
{"value":"B"}
{"value":"C"}

What did you see instead?

{"value":"A"}
{"value":"A"}
{"value":"C","A":{"value":"A"},"B":{"value":"A"}}

The first line is ok.
The second line is completely wrong.
The third line is almost ok.

C has two nested objects with a custom marshal and it works almost good.
B has just one and it prints the output of A.

@ianlancetaylor
Copy link
Contributor

Note that we don't use the issue tracker to ask questions. Please see https://golang.org/wiki/Questions .

@alexandrevicenzi
Copy link
Author

In my opinion, it's a bug since it works for some cases.

@dsnet
Copy link
Member

dsnet commented Sep 15, 2017

I should note that Go 1.0 had the user's expected behavior:

{"value":"A"}
{"value":"B"}
{"value":"C"}

The current output has been the case since Go1.1.

@dsnet dsnet added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Sep 15, 2017
@go101
Copy link

go101 commented Sep 15, 2017

Maybe Go 1.0 is buggy. I feel the results of the later versions are right.

func (this *B) MarshalJSON() ([]byte, error) {
	type Copy B
	c := (*Copy)(this)
	return json.Marshal(c)
}

The type *Copy defined in (*B).MarshalJSON has one method,
this method comes from (*A).MarshalJSON.
(In a type definition, the new defined type will not retain the methods directly defined on the source type).
json.Marshal(c) will call c.A.MarshalJSON() consequently,
this is why the json.Marshal(c) in (*B).MarshalJSON will return []byte("{\"value\":\"A\"}").

The *Copy type in (*C).MarshalJSON has no methods for the collision of (*A).MarshalJSON and (*B).MarshalJSON.

@ianlancetaylor
Copy link
Contributor

Doesn't seem to be anything to do here.

@golang golang locked and limited conversation to collaborators Mar 30, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

5 participants