- How to read & write json
- Concept: Build struct with zero value,
json.Unmarshal
sets properties - Recall
[]byte
<->string
conversion is cheap
- TODO
- Like
@JsonValue
for jackson
func (t *MyType) MarshalJSON() ([]byte, error) {
// NOTE: alias MyType if you have recursive structure
return json.Marshal(t.foo)
}
- Like
@JsonCreator
for jackson - GOTCHA: only works for Exported fields
func (t *MyType) UnmarshalJSON(data []byte) error {
var raw interface{}
//var raw []interface{} <-- if you expect a list/array/slice
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
//TODO: type assertion or switch on type
t.Foo = ...
return nil
}
- Important interfaces to implement:
driver.Valuer
(one method:Value
)json.Marshaler
(one method:MarshalJSON
)json.Unmarshaler
(one method:UnmarshalJSON
)sql.Scanner
(one method:Scan
)
- Use null types to distinguish unset values from zero values
- Runner-up: guregu/null
- See rdbms doc
- Goland can build structs from json
- GOTCHA: custom json Unmarshal method not called for Unexported fields (only Exported)
- Goland has an inspection for this
- Use
DisallowUnknownFields
for strict unmarshal - TODO: verify idiom: setDefaults before unmarshal, set derived after
- Standard lib lacks support for json5
- Just use nilable type (eg.
*int32
) - guregu/null.v4
- emvi/null
- light & simple implementation
- tests
- zero external deps
- Con: doesn't support custom MarshalText/UnmarshalText (important for toml & yaml)
kak-tus/nan- Far too many deps (gocql, etc)
- TODO: handling for missing properties
- TODO: handling for
$id
and$schema
- TODO: omitempty
- TODO: how to serialize (Marshal) properties alphabetical
- mapstructure
- Supports multiple serialization types
- Captures "remainder" or "extra" fields while unmarshaling
- Supports Embedded Structs and Squashing
- jsoniter
- Supports private fields (unlike standard json serde)
- Supports field type encoders/decoders