導入 is a simple data interchange format. Almost 15 years ago, we wrote about , which introduced the ability to serialize and deserialize Go types to and from JSON data. Since then, JSON has become the most popular data format used on the Internet. It is widely read and written by Go programs, and encoding/json now ranks as the 5th most imported Go package. JavaScript Object Notation (JSON) JSON in Go のサポート 時間とともに、パッケージはユーザーのニーズとともに進化し、 このブログ記事はGo 1.25の新しい実験についてです。 そして この投稿では、新しい主要な API バージョンを主張し、新しいパッケージの概要を提供し、それをどのように利用できるかを説明します。 encoding/json encoding/json/v2 encoding/json/jsontext Problems with コード / JSON コード / JSON 全体的に、 JSON でいくつかのデフォルト表示を含む任意の Go タイプを marshaling と unmarshaling のアイデアは、表示をカスタマイズする能力と組み合わせて、非常に柔軟であることが証明されています。 encoding/json Behavior flaws さまざまな行動の欠陥がある。 : encoding/json : Over the years, JSON has seen increased standardization in order for programs to properly communicate. Generally, decoders have become stricter at rejecting ambiguous inputs, to reduce the chance that two implementations will have different (successful) interpretations of a particular JSON value. Imprecise handling of JSON syntax currently accepts invalid UTF-8, whereas the latest Internet Standard (RFC 8259) requires valid UTF-8. The default behavior should report an error in the presence of invalid UTF-8, instead of introducing silent data corruption, which may cause problems downstream. encoding/json currently accepts objects with duplicate member names. RFC 8259 does not specify how to handle duplicate names, so an implementation is free to choose an arbitrary value, merge the values, discard the values, or report an error. The presence of a duplicate name results in a JSON value without a universally agreed upon meaning. This could be and has been exploited before (as in ). The default behavior should err on the side of safety and reject duplicate names. encoding/json exploited by attackers in security applications CVE-2017-12635 JSONはしばしばJSON実装を使用したプログラムとコミュニケーションするために使用され、nullがJSONアレイやオブジェクトであると期待されるデータ型に非マルシングされることを許さない。JSONは、JSONのマルシングをJSONのマルシングとしてマルシングするため、他の実装によって非マルシングする際にエラーを引き起こす可能性があります。調査では、ほとんどのGoユーザーは、ニルシークやマップが空のJSONアレイやオブジェクトとしてマルシングされることを好むことが示されました。 : When unmarshaling, a JSON object member name is resolved to a Go struct field name using a case-insensitive match. This is a surprising default, a potential security vulnerability, and a performance limitation. Case-insensitive unmarshaling Inconsistent calling of methods: Due to an implementation detail, MarshalJSON methods declared on a pointer receiver are inconsistently called by encoding/json. バグとみなされるが、これはあまりにも多くのアプリケーションが現在の行動に依存しているため修正できない。 API deficiencies The API of 困難または制限的かもしれない: encoding/json ユーザーはしばしば json.NewDecoder(r).Decode(v)を書き、入力の末尾に追跡ゴミを拒否しない。 オプションは Encoder と Decoder タイプに設定できますが、Marshal と Unmarshal 関数で使用することはできません。同様に、Marshaler と Unmarshaler インターフェイスを実装するタイプはオプションを利用できませんし、コール スタックのオプションをスループする方法はありません。 Compact、Indent、HTMLEscape 関数は []byte または io.Writer などのより柔軟なものに代わって bytes.Buffer に書き込みます。 パフォーマンス制限 内部実装の詳細を除き、Public API は、いくつかのパフォーマンス制限を課します。 : The interface method forces the implementation to allocate the returned . Also, the semantics require that verify that the result is valid JSON and also to reformat it to match the specified indentation. MarshalJSON MarshalJSON []byte encoding/json : The interface method requires that a complete JSON value be provided (without any trailing data). This forces to parse the JSON value to be unmarshaled in its entirety to determine where it ends before it can call . Afterwards, the method itself must parse the provided JSON value again. UnmarshalJSON UnmarshalJSON encoding/json UnmarshalJSON UnmarshalJSON : Even though the and types operate on an or , they buffer the entire JSON value in memory. The method for reading individual tokens is allocation-heavy and there is no corresponding API for writing tokens. Lack of streaming Encoder Decoder io.Writer io.Reader Decoder.Token さらに、Aの実施が or Method recursively calls the または 機能、その後、パフォーマンスは四角形になります。 MarshalJSON UnmarshalJSON Marshal Unmarshal Trying to fix 直接 encoding/json コード / JSON パッケージの新しい、互換性のない主要バージョンを導入することは重い考慮であり、可能であれば、既存のパッケージを修正しようとします。 新しい機能を追加することは比較的簡単ですが、既存の機能を変更することは困難です。残念ながら、これらの問題は既存のAPIの固有の結果であり、既存のAPI内で修正することはほぼ不可能です。 . Go 1 互換性の約束 原則として、別々の名前を宣言することができる、例えば、 または , but that is equivalent to creating a parallel namespace within the same package. これは、同じパッケージ内で並列のネームスペースを作成することに等しい。 (今後の呼びかけ) )で、これらの変更を別々の枠内で行うことができます。 Namespaceとは対照的に、 (今後の呼びかけ) ( ) MarshalV2 UnmarshalV2 encoding/json/v2 v2 v2 encoding/json v1 プランニング for コード/JSON/V2 コード/JSON/V2 新たな重大なバージョンの計画 spanned years. In late 2020, spurred on by the inability to fix issues in the current package, Daniel Martí (one of the maintainers of )は、最初に彼の考えを書いた。 パッケージは同じように見えるはずです. Separately, after previous work on the ジョー・ザイは失望した。 package needed to use a custom JSON implementation because プロトコルバッファの仕様が要求するより厳格なJSON標準に従うことができず、JSONを効率的にストリーミングすることもできなかった。 encoding/json encoding/json what a hypothetical v2 Go API for Protocol Buffers(プロトコルバッファー) THE protojson encoding/json JSONのより明るい未来が有益で実現可能だと信じて、ダニエルとジョーは力を合わせた。 そして (初期のコードはGo protobufモジュールからのJSONシリアリゼーション論理のポーリングバージョンである) 時間の経過とともに、ほかの人々(Roger Peppe、Chris Hines、Johan Brandhorst-Satzkorn、Damien Neil)は、デザインレビュー、コードレビュー、回帰テストを提供することによって、この取り組みに加わりました。 そして . v2 プロトタイプを作り始めた。 recorded meetings 会議ノート この仕事は最初から公開されており、私たちはますます広いGoコミュニティを関与し、最初は そして , そして、最近、 すべてのGoユーザーによるより広範なテストのためのGo実験(Go 1.25で利用可能)として使用されます。 GopherCon スピーチ 2023年末に投稿された記事 2025年初頭に発表された正式な提案 adopting encoding/json/v2 THE 取り組みは5年間続いており、多くの貢献者からのフィードバックを組み込んでおり、生産環境での使用から貴重な実験的経験を得ています。 v2 Go プロジェクトは、Google が雇用していない人々によって開発され、促進されており、Go 生態系の改善に専念する世界的なコミュニティと協力して取り組んでいることを示しています。 建物 ON コード / JSON / JSON コード / JSON / JSON 議論する前に、 API、まずは実験を導入します。 このパッケージは、Go で JSON を将来的に改善するための基礎を築くものです。 v2 encoding/json/jsontext JSON serialization in Go は、2 つの主要なコンポーネントに分割することができます。 文法に基づくJSON処理に関係する構文機能、および JSON 値と Go 値の関係を定義するセマンティックな機能。 「コード」と「デコード」の用語を用いて、シンタクティック機能性を記述し、「マーシャル」と「アンマーシャル」の用語を用いて、セマンティック機能を記述する。 この図はこの分離の概要を提供します。紫色のブロックはタイプを表し、青いブロックは機能または方法を表します。 パッケージは、単にシンタクスに関係する機能を含み、上半分は、 パッケージは、底半分が処理する合成データに意味を割り当てる機能を含みます。 jsontext json/v2 基本的な API 以下である。 jsontext package jsontext type Encoder struct { ... } func NewEncoder(io.Writer, ...Options) *Encoder func (*Encoder) WriteValue(Value) error func (*Encoder) WriteToken(Token) error type Decoder struct { ... } func NewDecoder(io.Reader, ...Options) *Decoder func (*Decoder) ReadValue() (Value, error) func (*Decoder) ReadToken() (Token, error) type Kind byte type Value []byte func (Value) Kind() Kind type Token struct { ... } func (Token) Kind() Kind THE package provides functionality for interacting with JSON at a syntactic level and derives its name from JSON JSON データの文法が文字通り呼ばれる場所 JSON はシンタクティックレベルでのみ相互作用するため、Go 反射に依存しない。 jsontext RFC 8259 第2部 JSON-text THE そして provide support for encoding and decoding JSON values and tokens. The constructors that affect the particular behavior of encoding and decoding. Unlike the and types declared in 新しいタイプは、In シンタクスとセマンティクスの区別を混乱させず、真のストリーミング方法で動作する。 Encoder Decoder Variable オプション Encoder Decoder v1 jsontext JSON 値は、データの完全な単位であり、Go では それは同一である。 イン . A JSON value is syntactically composed of one or more JSON tokens. A JSON token is represented in Go as the コンストラクターとアクセサリーの方法と同様です。 イン しかし、割り当てなしに任意のJSONトークンを表すように設計されています。 A名称 []byte RawMessage v1 opaque Token Token v1 基本的なパフォーマンスの問題を解決するために、 そして interface methods, we need an efficient way of encoding and decoding JSON as a streaming sequence of tokens and values. In We introduce the and インターフェイスで動作する方法 または 方法の実装が純粋にストリーミング方式でJSONを処理できるようにする。 MarshalJSON UnmarshalJSON v2 MarshalJSONTo UnmarshalJSONFrom Encoder Decoder したがって, the パッケージは、パッケージによって返される JSON 値の検証またはフォーマットに責任を負う必要はありません。 , また、提供する JSON 値の限界を決定する責任を負う必要はありません。 これらの責任は、 そして . json MarshalJSON UnmarshalJSON Encoder Decoder 導入 encoding/json/v2 コード/JSON/V2 Building on the パッケージ、今では実験を導入します。 package. It is designed to fix the aforementioned problems, while remaining familiar to users of the パッケージ:私たちの目的は、使用のための 手術する 同様に、直接移住した場合 . jsontext encoding/json/v2 v1 v1 mostly v2 この記事では、主に高レベルのAPIをカバーします。 使用方法の例については、読者に研究することを奨励します。 package or read . v2 the examples in the v2 Anton Zhiyanovのブログが話題をカバーしています。 基本的な API 以下である。 v2 package json func Marshal(in any, opts ...Options) (out []byte, err error) func MarshalWrite(out io.Writer, in any, opts ...Options) error func MarshalEncode(out *jsontext.Encoder, in any, opts ...Options) error func Unmarshal(in []byte, out any, opts ...Options) error func UnmarshalRead(in io.Reader, out any, opts ...Options) error func UnmarshalDecode(in *jsontext.Decoder, out any, opts ...Options) error THE そして 同様の署名を有する機能 , but accept options to configure their behavior. The そして 機能は直接操作するA または 一時的に構築する必要性を避けるため、 または こういう人から読んだり書いたりするだけです。 Marshal Unmarshal v1 MarshalWrite UnmarshalRead io.Writer io.Reader Encoder Decoder THE and 機能はAで動作する。 and 実は、前述の機能とは異なり、 , options are a first-class argument to each of the marshal and unmarshal functions, greatly extending the flexibility and configurability of the Marshal and unmarshal functions. オプションは、マルシャルおよび非マルシャル機能のそれぞれに一流の論点であり、非常に柔軟性と構成可能性を拡大します。 . There are in この記事には含まれていないもの。 MarshalEncode UnmarshalDecode jsontext.Encoder jsontext.Decoder v1 v2 さまざまなオプション available v2 Type-Specified Customization トピック 似たもの で、 タイプは、特定のインターフェイスを満たすことで、独自のJSON表示を定義できます。 v1 v2 type Marshaler interface { MarshalJSON() ([]byte, error) } type MarshalerTo interface { MarshalJSONTo(*jsontext.Encoder) error } type Unmarshaler interface { UnmarshalJSON([]byte) error } type UnmarshalerFrom interface { UnmarshalJSONFrom(*jsontext.Decoder) error } THE そして インターフェイスは、内部のものと同一です。 . The new そして インターフェイスでは、タイプがJSONとして自己を表すことを可能にします。 or . This allows options to be forwarded down the call stack, since options can be retrieved via the accessor method on the または . Marshaler Unmarshaler v1 MarshalerTo UnmarshalerFrom jsontext.Encoder jsontext.Decoder Options Encoder Decoder こちら JSON オブジェクト メンバーの順序を維持するカスタム型を実装する方法の例です。 THE OrderedObject CALLER-SPECIFIED CUSTOMIZATION イン , the caller of そして また、Caller-specified 関数が Type-defined メソッドまたは特定のタイプのデフォルト表示に優先する任意のタイプのカスタム JSON 表示を指定できます。 v2 Marshal Unmarshal func WithMarshalers(*Marshalers) Options type Marshalers struct { ... } func MarshalFunc[T any](fn func(T) ([]byte, error)) *Marshalers func MarshalToFunc[T any](fn func(*jsontext.Encoder, T) error) *Marshalers func WithUnmarshalers(*Unmarshalers) Options type Unmarshalers struct { ... } func UnmarshalFunc[T any](fn func([]byte, T) error) *Unmarshalers func UnmarshalFromFunc[T any](fn func(*jsontext.Decoder, T) error) *Unmarshalers and マルシェルを構築し、Aに渡すことができます。 電話利用 to override the marshaling of particular types. Similarly, そして 同様のカスタマイズのサポート . MarshalFunc MarshalToFunc Marshal WithMarshalers UnmarshalFunc UnmarshalFromFunc Unmarshal 例では、この機能がすべてのセリリウム化を可能にする方法を示しています。 types to be handled by the パッケージ The ProtoJSON proto.Message protojson Behavior differences たとえ 行動する目的 the same as , its behavior has changed で問題を解決するために、 特に特に: v2 大抵 v1 いくつかの方法で v1 reports an error in the presence of invalid UTF-8. v2 reports an error if a JSON object contains a duplicate name. v2 marshals a nil Go slice or Go map as an empty JSON array or JSON object, respectively. v2 unmarshals a JSON object into a Go struct using a case-sensitive match from the JSON member name to the Go field name. v2 redefines the tag option to omit a field if it would have encoded as an “empty” JSON value (which are , , , and ). v2 omitempty null "" [] {} reports an error when trying to serialize a , which currently has , but provides options to let the caller decide. v2 time.Duration no default representation ほとんどの行動の変更には、構造タグオプションまたは呼び出し指定オプションが存在し、行動を構成して動作することができます。 または セマンティクス、あるいは他の呼び出し決定的な行動。 より多くの情報のために v1 v2 “Migrating to v2” Performance optimizations The 業績 of is roughly at parity with 時には少し速くなりますが、時には少し遅くなります。 業績 of is significantly faster than , ベンチマークで最大10倍の改善を示す。 Marshal v2 v1 Unmarshal v2 v1 より大きなパフォーマンスを得るために、既存の実装 and 移住も実施しなければならない。 そして JSON を純粋にストリーミングする方法で処理することで恩恵を受けることができるように、例えば、OpenAPI 仕様のリクルーシブパッサーシングは 特定の Kubernetes サービスのパフォーマンスを大幅に損なう方法(参照) ), while switching to サイズの順序で性能を向上させます。 Marshaler Unmarshaler MarshalerTo UnmarshalerFrom UnmarshalJSON キューバ / キューバ / キューバ / キューバ / キューバ / キューバ UnmarshalJSONFrom より詳しい情報は、The repository. go-json-experiment/jsonbench 逆向きに改善 コード / JSON コード / JSON 我々は、Go標準ライブラリの2つの別々のJSON実装を避けたいので、キャップの下で、 という観点で実施されている。 . v1 v2 このアプローチにはいくつかの利点があります: : The and functions in or represent a set of default behaviors that operate according to or semantics. Options can be specified that configure or to operate with entirely , mostly with a some , a mix of or , mostly with some , or entirely semantics. This allows for gradual migration between the default behaviors of the two versions. Gradual migration Marshal Unmarshal v1 v2 v1 v2 Marshal Unmarshal v1 v1 v2 v1 v2 v2 v1 v2 機能の継承:バックアップ互換性のある機能が v2 に追加されるにつれて、本質的に v1 で利用可能になります。 たとえば、v2 は inline または format などのいくつかの新しい構造タグオプションのサポートを追加し、MarshalJSONTo および UnmarshalJSONFrom インターフェイス メソッドのサポートも追加します。 一般的に使用されているパッケージのメンテナンスには大きな努力が必要です. v1 と v2 が同じ実装を使用することにより、メンテナンスの負担が軽減されます. 一般的に、単一の変更はバグを修正し、パフォーマンスを改善したり、両方のバージョンに機能を追加したりします. 同等の v1 変更で v2 変更をバックポートする必要はありません. While select parts of 時間の経過によって消滅する可能性がある(仮定) 実験から卒業した後、全体としてのパッケージは決して削減されません。 will be encouraged, but not required. The Go project will not drop support for . v1 v2 v2 v1 実験 同 ジョン2 ジョン2 最新の火災は、 そして パッケージはデフォルトでは表示されていません. To use them, build your code with あなたの環境や、 実験の性質は、APIが不安定であり、将来に変化する可能性があることである。APIは不安定であるが、実装は高品質であり、いくつかの主要プロジェクトで生産に成功してきた。 encoding/json/jsontext encoding/json/v2 GOEXPERIMENT=jsonv2 goexperiment.jsonv2 という事実 is implemented in terms of つまり、基本的な実施は、 is completely different when building under the experiment. Without changing any code, you should be able to run your tests under そして、理論的には、何も新しいことは失敗しないはずです。 v1 v2 v1 jsonv2 jsonv2 GOEXPERIMENT=jsonv2 go test ./... The re-implementation of In terms of 同一の境界内での行動を提供することを目的としている。 , though some differences might be observable such as the exact wording of error messages. We encourage you to run your tests under ・あらゆる回帰を報告する . v1 v2 Go 1 互換性の約束 jsonv2 トラッカーの問題について Go 1.25 での実験になることは、正式に採用するための重要なマイルストーンです。 そして 図書館の基本的な目的は、しかし、 あなたのフィードバックは、私たちの次のステップと、この実験の結果を決定し、それは努力の放棄から、Go 1.26の安定パッケージとしての採用に至るまで、あらゆる結果をもたらす可能性があります。 Goの未来を決めるのに役立ちます。 encoding/json/jsontext encoding/json/v2 jsonv2 go.dev/issue/71497 Joe Tsai, Daniel Martí, Johan Brandhorst-Satzkorn, Roger Peppe, Chris Hines, and Damien Neil この記事は、CC BY 4.0 DEED ライセンスの下で The Go Blog で利用できます。 GO BLOG GO BLOG Photo by on Jr Korpa Unsplash Jr Korpa Unsplashについて