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. 2 About me • Shunta Komatsu • Backend Engineer at

    Merpay ◦ Developing the payment platform • Likes ◦ Dogs ◦ Neovim
  2. 4 Agenda 1. encoding/json/v1 package の問題点 2. encoding/json/v2 package の紹介

    3. パフォーマンスとマイグレーション 4. 議論の動向
  3. 9 encoding/json/v1 package の問題点 1. 機能不足 2. API の欠陥 3.

    パフォーマンスの制限 4. 動作上の欠陥
  4. 15 API の欠陥 • io.Reader から unmarshal できない ◦ json.Unmarshal

    は []byte を引数に取る ◦ io.Reader を入力するためには中間デコーダが必要 ▪ json.NewDecoder(r).Decode(v) ▪ 末尾の文字列を許容するなどの直感に反する動作 (#36225)
  5. 16 API の欠陥 • Marshal, Unmarshal や MarshalJSON, UnmarshalJSON は動作を設定

    するオプションを受け付けない ◦ 動作を設定するためにはやはり Encoder, Decoder が必要
  6. 17 • MarshalJSON は []byte を返すので、その分のメモリをアロケートする必要 がある • MarshalJSON と

    UnmarshalJSON は内部で 2 回テキストの解析を行うため 効率が悪い ◦ オブジェクトの型情報の収集 -> 値のパース • ストリーミングの欠如 ◦ Encoder.Encode と Decoder.Decode は io.Writer と io.Reader を引数に取るにも関わらず、JSON 値全体をメモリにバッファ する パフォーマンスの制限
  7. 18 動作上の欠陥 • RFC (RFC 8259) に定義されている JSON の仕様とのズレ ◦

    invalid な UTF-8 が許容されている ◦ JSON object の key の重複が許容されている
  8. 19 動作上の欠陥 • MarshalJSON と UnmarshalJSON は reflection を使っているため、アド レスが取得できないと定義していても呼び出されない

    • unmarshal は case-insensitive に行われる • 返されるエラーの型に一貫性がない ◦ 構造化されたエラーを返したり、構造化されていないエラーを返す
  9. 21 encoding/json/v2 の思想と目標 • (ほぼ) 後方互換を保つ • より正確に • よりパフォーマンス良く

    • より柔軟に • 使いやすく、誤用しにくい • unsafe package は利用しない
  10. 24 encoding/json/jsontext package • Encoder と Decoder は JSON token

    と value の読み書きをする ◦ JSON テキストを純粋なストリーミング形式で処理する • NewEncoder と NewDecoder はオプションを受け付ける
  11. 25 • 可変長の Options 型によって動作の設定が可能 • Options interface は jsonopts

    package に定義されている Options type https://github.com/go-json-experiment/json/blob/master/jsontext/options.go
  12. 28 encoding/json/v2 package • Marshal, Unmarshal ◦ v1 の Marshal

    と Unmarshal とほぼ同じ • MarshalWrite, UnmarshalRead ◦ []byte の代わりに io.Writer と io.Reader を受け付ける • MarshalEncode, UnmarshalDecode ◦ *jsontext.Encoder と *jsontext.Decoder を受け付ける
  13. 33 Struct tag options • v2 は以下の struct tag をサポート

    ◦ omitzero <- new! ◦ omitempty ◦ string ◦ nocase <- new! ◦ inline <- new! ◦ unknown <- new! ◦ format <- new!
  14. 36 Options type • 可変長の Options 型によって動作の設定が可能 • Options interface

    は jsonopts package に定義されている https://github.com/go-json-experiment/json/blob/master/options.go
  15. 45 今すぐ参加できる discussion marshal 時に nil slice と nil map

    を空の JSON array や object として扱う か、JSON null として扱うか
  16. 48 個人的な所感 • パフォーマンスや API の柔軟性、RFC への準拠による正確性に加えて、後方 互換性やマイグレーションにつても考慮されており、提案は全体的によく考えら れている •

    これ以上パフォーマンスを上げる場合は 3rd party の JSON ライブラリによう にコード生成やアセンブリレベルでの最適化が必要 ◦ 標準パッケージがやるべきではない? • JSON の文法を処理する jsontext pacakge と Go の値と作用する json package に分けるアイデアは綺麗な設計
  17. 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
  18. 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