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: interface{} not being stringified when JSON ",string" tag is used #32055

Open
docmerlin opened this issue May 15, 2019 · 4 comments
Labels
help wanted NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@docmerlin
Copy link

docmerlin commented May 15, 2019

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

1.12.5 playground

Does this issue reproduce with the latest release?

yes

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

NACL

What did you do?

https://play.golang.org/p/Q4JdghzkBI-

What did you expect to see?

interface{} fields that point to integers should be converted to strings when the string tag is used.

The documentation says:
It applies only to fields of string, floating point, integer, or boolean types

but it also says:

Interface values encode as the value contained in the interface. A nil interface value encodes as the null JSON value.

What did you see instead?

They were not converted to strings.

@andybons andybons changed the title interface{} not being stringified when JSON ",string" tag is used encoding/json: interface{} not being stringified when JSON ",string" tag is used May 15, 2019
@FiloSottile
Copy link
Contributor

/cc @dsnet @mvdan

@FiloSottile FiloSottile added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label May 15, 2019
@FiloSottile FiloSottile added this to the Go1.14 milestone May 15, 2019
@andybons
Copy link
Member

andybons commented May 15, 2019

This is due to the encoder determining whether to quote the value while looking at the type of field (in this case reflect.Interface within typeFields). Since there are only a subset of types permitted and reflect.Interface is not one of them, quoted is never set to true. So when it gets to the intEncoder it’s not quoting the value.

Adding reflect.Interface to the list of allowed types has the desired effect for an int, but then if you put a slice of strings into the field, it will recursively encode the types and quote them, so you’ll end up with

{"Thing": ["\"val\""]} instead of the desired {"Thing": ["val"]}

The same is true for maps and any other data structure where it needs to recursively encode values.

This isn’t to say we shouldn’t fix these cases, but it provides some context as to why this is happening.

@mvdan
Copy link
Member

mvdan commented May 29, 2019

What @andybons said, pretty much. I agree the current docs can be confusing about this edge case, but I wonder if it's worth going through the trouble of changing the behavior of this edge case.

Perhaps a simpler fix is to clarify the docs. On the other hand, if someone wants to investigate a fix in the code, just be careful to not break any of the existing tests.

@kawakami-o3
Copy link
Contributor

I investigated @andybons 's suggestion, and I noticed that it failed to the round-trip test. In the example of @docmerlin , the initial value, int(3), becomes string("3") after making a round trip.

Is there any suggestion? I want to investigate more.

@rsc rsc modified the milestones: Go1.14, Backlog Oct 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted 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

7 participants