如何在 JSON 中编组和解组 big.Int ?

kbo*_*ino 2 json biginteger go

问题How to marshal JSON with bigints? 是关于将big.Int值封送到 JSON 中的字符串。这个问题问,编组和解 组如何将本机big.Int值视为数字作为JSON 中的

传递以这种方式编组的大值可能与 JSON 的其他实现不兼容,特别是 JavaScript 和jq,如RFC 7159所述:

请注意,当使用此类软件时,整数且在该范围内的数字[-(2**53)+1, (2**53)-1]是可互操作的,因为实现将在其数值上完全一致。

kbo*_*ino 8

创建一个BigInt实现以下json.Marshaler内容的自定义类型json.Unmarshaler

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
}
Run Code Online (Sandbox Code Playgroud)

理由:

  • 作为结构类型嵌入big.Int而不是作为子类型实现big.Int,以便保留方法(Add、SetString 等)
  • MarshalJSON 采用值接收器,以便使用编组值BigInt不必使用指针
  • UnmarshalJSON 采用指针接收器,因为它修改接收器;但是,使用 BigInt 的类型仍然不必使用指针
  • UnmarshalJSON 适用于临时值,因为 SetString 方法在发生错误时其接收器上有未定义的行为

因为big.Int零值很有用并且等于数字 0。