Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Future of encoding/json

The Future of encoding/json

Shunta Komatsu

December 01, 2023
Tweet

More Decks by Shunta Komatsu

Other Decks in Technology

Transcript

  1. 1
    The Future of encoding/json
    Go Conference mini 2023 Winter IN KYOTO
    Shunta Komatsu

    View full-size slide

  2. 2
    About me
    ● Shunta Komatsu
    ● Backend Engineer at Merpay
    ○ Developing the payment platform
    ● Likes
    ○ Dogs
    ○ Neovim

    View full-size slide

  3. 3
    このセッションの目的
    ● 現在提案されている encoding/json/v2 について理解してもらう
    ● 興味を持った方が discussion に参加することで Go コミュニティに貢献する
    きっかけを作る

    View full-size slide

  4. 4
    Agenda
    1. encoding/json/v1 package の問題点
    2. encoding/json/v2 package の紹介
    3. パフォーマンスとマイグレーション
    4. 議論の動向

    View full-size slide

  5. 5
    encoding/json package
    使ったことありますか?✋

    View full-size slide

  6. 6
    encoding/json package
    encoding/json は 5 番目 に多く import されている (らしい)
    Marshal (encode)
    Unmarshal (decode)

    View full-size slide

  7. 7
    encoding/json package
    json パッケージができたのは 2008 年

    View full-size slide

  8. 8
    encoding/json/v1 package の問題点

    View full-size slide

  9. 9
    encoding/json/v1 package の問題点
    1. 機能不足
    2. API の欠陥
    3. パフォーマンスの制限
    4. 動作上の欠陥

    View full-size slide

  10. 10
    機能不足
    ● 92 個の encoding/json 関連の proposal や feature request

    View full-size slide

  11. 11
    機能不足
    ● 92 個の encoding/json 関連の proposal や feature request

    View full-size slide

  12. 12
    機能不足

    View full-size slide

  13. 13
    機能不足
    ● 92 個の encoding/json 関連の proposal や feature request

    View full-size slide

  14. 14
    機能不足

    View full-size slide

  15. 15
    API の欠陥
    ● io.Reader から unmarshal できない
    ○ json.Unmarshal は []byte を引数に取る
    ○ io.Reader を入力するためには中間デコーダが必要
    ■ json.NewDecoder(r).Decode(v)
    ■ 末尾の文字列を許容するなどの直感に反する動作 (#36225)

    View full-size slide

  16. 16
    API の欠陥
    ● Marshal, Unmarshal や MarshalJSON, UnmarshalJSON は動作を設定
    するオプションを受け付けない
    ○ 動作を設定するためにはやはり Encoder, Decoder が必要

    View full-size slide

  17. 17
    ● MarshalJSON は []byte を返すので、その分のメモリをアロケートする必要
    がある
    ● MarshalJSON と UnmarshalJSON は内部で 2 回テキストの解析を行うため
    効率が悪い
    ○ オブジェクトの型情報の収集 -> 値のパース
    ● ストリーミングの欠如
    ○ Encoder.Encode と Decoder.Decode は io.Writer と
    io.Reader を引数に取るにも関わらず、JSON 値全体をメモリにバッファ
    する
    パフォーマンスの制限

    View full-size slide

  18. 18
    動作上の欠陥
    ● RFC (RFC 8259) に定義されている JSON の仕様とのズレ
    ○ invalid な UTF-8 が許容されている
    ○ JSON object の key の重複が許容されている

    View full-size slide

  19. 19
    動作上の欠陥
    ● MarshalJSON と UnmarshalJSON は reflection を使っているため、アド
    レスが取得できないと定義していても呼び出されない
    ● unmarshal は case-insensitive に行われる
    ● 返されるエラーの型に一貫性がない
    ○ 構造化されたエラーを返したり、構造化されていないエラーを返す

    View full-size slide

  20. 20
    encoding/json/v2 package の紹介

    View full-size slide

  21. 21
    encoding/json/v2 の思想と目標
    ● (ほぼ) 後方互換を保つ
    ● より正確に
    ● よりパフォーマンス良く
    ● より柔軟に
    ● 使いやすく、誤用しにくい
    ● unsafe package は利用しない

    View full-size slide

  22. 22
    Overview
    https://github.com/golang/go/discussions/63397

    View full-size slide

  23. 23
    encoding/json/jsontext package
    https://github.com/golang/go/discussions/63397

    View full-size slide

  24. 24
    encoding/json/jsontext package
    ● Encoder と Decoder は JSON token と value の読み書きをする
    ○ JSON テキストを純粋なストリーミング形式で処理する
    ● NewEncoder と NewDecoder はオプションを受け付ける

    View full-size slide

  25. 25
    ● 可変長の Options 型によって動作の設定が可能
    ● Options interface は jsonopts package に定義されている
    Options type
    https://github.com/go-json-experiment/json/blob/master/jsontext/options.go

    View full-size slide

  26. 26
    SyntacticError type
    ● JSON の文法に準拠していないことに起因するエラーは SyntacticError と
    して返される

    View full-size slide

  27. 27
    encoding/json/v2 package
    https://github.com/golang/go/discussions/63397

    View full-size slide

  28. 28
    encoding/json/v2 package
    ● Marshal, Unmarshal
    ○ v1 の Marshal と Unmarshal とほぼ同じ
    ● MarshalWrite, UnmarshalRead
    ○ []byte の代わりに io.Writer と io.Reader を受け付ける
    ● MarshalEncode, UnmarshalDecode
    ○ *jsontext.Encoder と *jsontext.Decoder を受け付ける

    View full-size slide

  29. 29
    https://github.com/golang/go/discussions/63397
    デフォルトの挙動の変更

    View full-size slide

  30. 30
    ● key を case-sensitive に比較する
    デフォルトの挙動の変更

    View full-size slide

  31. 31
    ● invalid な UTF-8 を許容しない
    デフォルトの挙動の変更

    View full-size slide

  32. 32
    ● key の重複を許容しない
    デフォルトの挙動の変更

    View full-size slide

  33. 33
    Struct tag options
    ● v2 は以下の struct tag をサポート
    ○ omitzero <- new!
    ○ omitempty
    ○ string
    ○ nocase <- new!
    ○ inline <- new!
    ○ unknown <- new!
    ○ format <- new!

    View full-size slide

  34. 34
    ● omitzero
    ○ 値がゼロ値のときは marshal 時に省略される
    Struct tag options

    View full-size slide

  35. 35
    ● format
    ○ serialize するときの format を指定できる
    Struct tag options

    View full-size slide

  36. 36
    Options type
    ● 可変長の Options 型によって動作の設定が可能
    ● Options interface は jsonopts package に定義されている
    https://github.com/go-json-experiment/json/blob/master/options.go

    View full-size slide

  37. 37
    SemanticError type
    ● Go と JSON 間で値を関連付けるときに発生するエラーは SemanticError
    として返される

    View full-size slide

  38. 38
    encoding/json/v2 package
    https://github.com/golang/go/discussions/63397

    View full-size slide

  39. 39
    パフォーマンスとマイグレーション

    View full-size slide

  40. 40
    パフォーマンス
    https://github.com/go-json-experiment/jsonbench/blob/master/images/benchmark-marshal-concrete.png

    View full-size slide

  41. 41
    パフォーマンス
    https://github.com/go-json-experiment/jsonbench/blob/master/images/benchmark-unmarshal-concrete.png

    View full-size slide

  42. 42
    マイグレーション

    View full-size slide

  43. 43
    議論の動向

    View full-size slide

  44. 44
    golang/go で議論中

    View full-size slide

  45. 45
    今すぐ参加できる discussion
    marshal 時に nil slice と nil map を空の JSON array や object として扱う
    か、JSON null として扱うか

    View full-size slide

  46. 46
    今すぐ参加できる discussion
    新しい Options を提案することも可能

    View full-size slide

  47. 48
    個人的な所感
    ● パフォーマンスや API の柔軟性、RFC への準拠による正確性に加えて、後方
    互換性やマイグレーションにつても考慮されており、提案は全体的によく考えら
    れている
    ● これ以上パフォーマンスを上げる場合は 3rd party の JSON ライブラリによう
    にコード生成やアセンブリレベルでの最適化が必要
    ○ 標準パッケージがやるべきではない?
    ● JSON の文法を処理する jsontext pacakge と Go の値と作用する json
    package に分けるアイデアは綺麗な設計

    View full-size slide

  48. 49
    まとめ
    ● encoding/json/v2 は v1 が持っている機能不足、API の欠陥、パフォーマ
    ンスの制限、動作の欠陥といった問題点を解決・向上する提案
    ● jsontext と json の 2 つのパッケージに分けることで、”JSON の文法的な
    処理” と “Go の値との相互作用を行う意味的な処理” を効率的に実装している
    ● repository: https://github.com/go-json-experiment/json
    ● discussion : https://github.com/golang/go/discussions/63397

    View full-size slide

  49. 50
    References
    ● “The Future of JSON in Go” by Joe Tsai at GopherCon 2023 (link)
    ● https://github.com/go-json-experiment/json
    ● https://github.com/golang/go/discussions/63397

    View full-size slide

  50. 51
    よい JSON ライフを!👋

    View full-size slide