Skip to content

Latest commit

 

History

History
107 lines (78 loc) · 3.39 KB

json.md

File metadata and controls

107 lines (78 loc) · 3.39 KB

Overview

  • How to read & write json

Unmarshal (Parse, Deserialize, Decode)

  1. Concept: Build struct with zero value, json.Unmarshal sets properties
  2. Recall []byte <-> string conversion is cheap

Marshal (Write, Serialize, Encode)

  1. TODO

Custom Marshal

  1. Like @JsonValue for jackson
func (t *MyType) MarshalJSON() ([]byte, error) {

    // NOTE: alias MyType if you have recursive structure

    return json.Marshal(t.foo)
}

Custom Unmarshal

  1. Like @JsonCreator for jackson
  2. 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
}

Null handling

  1. Important interfaces to implement:

Idioms

  1. Use null types to distinguish unset values from zero values
    1. Runner-up: guregu/null
    2. See rdbms doc
  2. Goland can build structs from json
  3. GOTCHA: custom json Unmarshal method not called for Unexported fields (only Exported)
    1. Goland has an inspection for this
  4. Use DisallowUnknownFields for strict unmarshal
  5. TODO: verify idiom: setDefaults before unmarshal, set derived after
  6. Standard lib lacks support for json5

Preferred tools

  1. Just use nilable type (eg. *int32)
  2. guregu/null.v4
  3. emvi/null
    1. light & simple implementation
    2. tests
    3. zero external deps
    4. Con: doesn't support custom MarshalText/UnmarshalText (important for toml & yaml)

Rejected tools

  1. kak-tus/nan
    1. Far too many deps (gocql, etc)

TODO: organize

  • TODO: handling for missing properties
  • TODO: handling for $id and $schema
  • TODO: omitempty
  • TODO: how to serialize (Marshal) properties alphabetical

Alternatives

  1. mapstructure
    1. Supports multiple serialization types
    2. Captures "remainder" or "extra" fields while unmarshaling
    3. Supports Embedded Structs and Squashing
  2. jsoniter
    1. Supports private fields (unlike standard json serde)
    2. Supports field type encoders/decoders

Other Resources

  1. https://pkg.go.dev/encoding/json
  2. https://gobyexample.com/json
  3. https://linuxhint.com/marshal-unmarshal-golang/
  4. http://choly.ca/post/go-json-marshalling/
  5. https://thedeveloperblog.com/go/json-go
  6. https://www.practical-go-lessons.com/chap-25-json-and-xml
  7. https://yourbasic.org/golang/json-example/