Documentation ¶
Overview ¶
Package json provides functions for marshaling and unmarshaling JSON in a format that is backwards-compatible with Amino JSON encoding. This mostly differs from encoding/json in encoding of integers (64-bit integers are encoded as strings, not numbers), and handling of interfaces (wrapped in an interface object with type/value keys).
JSON tags (e.g. `json:"name,omitempty"`) are supported in the same way as encoding/json, as is custom marshaling overrides via the json.Marshaler and json.Unmarshaler interfaces.
Note that not all JSON emitted by CometBFT is generated by this library; some is generated by encoding/json instead, and kept like that for backwards compatibility.
Encoding of numbers uses strings for 64-bit integers (including unspecified ints), to improve compatibility with e.g. Javascript (which uses 64-bit floats for numbers, having 53-bit precision):
int32(32) // Output: 32 uint32(32) // Output: 32 int64(64) // Output: "64" uint64(64) // Output: "64" int(64) // Output: "64" uint(64) // Output: "64"
Encoding of other scalars follows encoding/json:
nil // Output: null true // Output: true "foo" // Output: "foo" "" // Output: ""
Slices and arrays are encoded as encoding/json, including base64-encoding of byte slices with additional base64-encoding of byte arrays as well:
[]int64(nil) // Output: null []int64{} // Output: [] []int64{1, 2, 3} // Output: ["1", "2", "3"] []int32{1, 2, 3} // Output: [1, 2, 3] []byte{1, 2, 3} // Output: "AQID" [3]int64{1, 2, 3} // Output: ["1", "2", "3"] [3]byte{1, 2, 3} // Output: "AQID"
Maps are encoded as encoding/json, but only strings are allowed as map keys (nil maps are not emitted as null, to retain Amino backwards-compatibility):
map[string]int64(nil) // Output: {} map[string]int64{} // Output: {} map[string]int64{"a":1,"b":2} // Output: {"a":"1","b":"2"} map[string]int32{"a":1,"b":2} // Output: {"a":1,"b":2} map[bool]int{true:1} // Errors
Times are encoded as encoding/json, in RFC3339Nano format, but requiring UTC time zone (with zero times emitted as "0001-01-01T00:00:00Z" as with encoding/json):
time.Date(2020, 6, 8, 16, 21, 28, 123, time.FixedZone("UTC+2", 2*60*60)) // Output: "2020-06-08T14:21:28.000000123Z" time.Time{} // Output: "0001-01-01T00:00:00Z" (*time.Time)(nil) // Output: null
Structs are encoded as encoding/json, supporting JSON tags and ignoring private fields:
type Struct struct{ Name string Value int32 `json:"value,omitempty"` private bool } Struct{Name: "foo", Value: 7, private: true} // Output: {"Name":"foo","value":7} Struct{} // Output: {"Name":""}
Registered types are encoded with type wrapper, regardless of whether they are given as interface or bare struct, but inside structs they are only emitted with type wrapper for interface fields (this follows Amino behavior):
type Vehicle interface { Drive() error } type Car struct { Wheels int8 } func (c *Car) Drive() error { return nil } RegisterType(&Car{}, "vehicle/car") Car{Wheels: 4} // Output: {"type":"vehicle/car","value":{"Wheels":4}} &Car{Wheels: 4} // Output: {"type":"vehicle/car","value":{"Wheels":4}} (*Car)(nil) // Output: null Vehicle(Car{Wheels: 4}) // Output: {"type":"vehicle/car","value":{"Wheels":4}} Vehicle(nil) // Output: null type Struct struct { Car *Car Vehicle } Struct{Car: &Car{Wheels: 4}, Vehicle: &Car{Wheels: 4}} // Output: {"Car": {"Wheels: 4"}, "Vehicle": {"type":"vehicle/car","value":{"Wheels":4}}}
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Marshal ¶
Marshal marshals the value as JSON, using Amino-compatible JSON encoding (strings for 64-bit numbers, and type wrappers for registered types).
func MarshalIndent ¶
MarshalIndent marshals the value as JSON, using the given prefix and indentation.
func RegisterType ¶
RegisterType registers a type for Amino-compatible interface encoding in the global type registry. These types will be encoded with a type wrapper `{"type":"<type>","value":<value>}` regardless of which interface they are wrapped in (if any). If the type is a pointer, it will still be valid both for value and pointer types, but decoding into an interface will generate the a value or pointer based on the registered type.
Should only be called in init() functions, as it panics on error.
Types ¶
This section is empty.