The question How to marshal JSON with bigints? is about marshaling big.Int
values into strings in JSON. This question asks, how does one marshal and unmarshal big.Int
values natively as numbers in JSON?
Passing around large values marshaled in this manner may be incompatible with other implementations of JSON, particularly JavaScript and jq, as RFC 7159 notes:
Note that when such software is used, numbers that are integers and are in the range
[-(2**53)+1, (2**53)-1]
are interoperable in the sense that implementations will agree exactly on their numeric values.
Create a custom type BigInt
which implements json.Marshaler
and json.Unmarshaler
like the following:
import (
"fmt"
"math/big"
)
type BigInt struct {
big.Int
}
func (b BigInt) MarshalJSON() ([]byte, error) {
return []byte(b.String()), nil
}
func (b *BigInt) UnmarshalJSON(p []byte) error {
if string(p) == "null" {
return nil
}
var z big.Int
_, ok := z.SetString(string(p), 10)
if !ok {
return fmt.Errorf("not a valid big integer: %s", p)
}
b.Int = z
return nil
}
Rationale:
big.Int
instead of as a subtype of big.Int
so that the methods (Add, SetString, etc.) are keptBigInt
don't have to use pointersAs with big.Int
the zero value is useful and is equal to the number 0.