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

math/big: big.Int (incorrectly) marshals to a number instead of a string #28154

Closed
alvarogzp opened this issue Oct 11, 2018 · 5 comments
Closed

Comments

@alvarogzp
Copy link

I am using go version go1.11 linux/amd64, and reproduced this issue with the latest version (1.11).

Type Int on package "math/big" implements both [Un]marshalText and [Un]marshalJSON, the later just calling its *Text counterpart: https://golang.org/src/math/big/intmarsh.go?s=1964:2010#L64

According to json.Marshal and json.Unmarshal documentation, both functions are not equivalent. [Un]marshalJSON works with raw JSON types, but [Un]marshalText only with previously-unquoted strings. The documentation also says that [Un]marshalJSON has priority over [Un]marshalText.

So, with those premises, currently big.Int is being marshaled into a number, as their [Un]marshalJSON functions are being called and they don't quote the result after calling [Un]marshalText on the big.Int.
I think it should marshal into a string, as big.Float does (because it only implements [Un]marshalText). Also, other tools usually work and expect string representations for big numbers.

Here you can see the result of marshaling a struct with a big.Int and a big.Float: https://play.golang.org/p/WIILuWzr57S
Note how the Float is properly quoted and marshaled as a string but the Int isn't.

I propose doing one of the following things:

  • Remove [Un]marshalJSON from https://golang.org/src/math/big/intmarsh.go. According to a comment, they are only there to provide "backwards compatibility" with programs that search for those methods.
  • Modify big.Int's [Un]marshalJSON to quote the string it produces and unquote the one it receives, so that it mimics what json.[Un]marshal does before and after calling [Un]marshalText.
  • If marshaling big.Int to a number is the desired behavior, make it explicit by removing [Un]marshalText from big.Int (as in that case, they won't apply), and also make big.Float marshal to a number too.
@alvarogzp alvarogzp changed the title big.Int (incorrectly) marshals to a number instead of a string math/big: big.Int (incorrectly) marshals to a number instead of a string Oct 11, 2018
@slrz
Copy link

slrz commented Oct 11, 2018

It's not possible to change the JSON marshaling behaviour of big.Ints for Go1. Even for Go2 I'm skeptical because of the breakage this would result in.

@rsc
Copy link
Contributor

rsc commented Oct 11, 2018

The JSON form of a big.Int is a json integer - not a quoted string.
The text form of a big.Int is the decimal text.
Yes, the same code generates both.
But because the JSON package prefers the JSON methods over the Text methods, there is no problem here.

Note that JSON imposes no limit on the size of decimal strings.

@rsc rsc closed this as completed Oct 11, 2018
@alvarogzp
Copy link
Author

alvarogzp commented Oct 11, 2018

@rsc what about the inconsistency with big.Float marshaler generating a quoted string?

@rsc
Copy link
Contributor

rsc commented Oct 11, 2018

If I had it to do again, I'd probably insist on big.Float having a MarshalJSON to avoid the quoting. But we missed that boat. Even for Go 2 it's not worth fixing.

@alvarogzp
Copy link
Author

ok, thanks for the explanation!

@golang golang locked and limited conversation to collaborators Oct 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants