Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to marshal and unmarshal big.Int in JSON?

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.

like image 401
kbolino Avatar asked Jan 20 '26 10:01

kbolino


1 Answers

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:

  • Implemented as a struct type embedding big.Int instead of as a subtype of big.Int so that the methods (Add, SetString, etc.) are kept
  • MarshalJSON takes a value receiver so that marshaled values using BigInt don't have to use pointers
  • UnmarshalJSON takes a pointer receiver because it modifies the receiver; however, types using BigInt still don't have to use pointers
  • UnmarshalJSON works on a temporary value because the SetString method has undefined behavior on its receiver in the case of errors

As with big.Int the zero value is useful and is equal to the number 0.

like image 195
kbolino Avatar answered Jan 23 '26 03:01

kbolino



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!