メモリ内オブジェクトの読み込みを行わずに大規模なデータ ストリームを JSON でエンコードする
大規模なデータ ストリームが含まれるシナリオでは、json すべてのオブジェクトを同時にメモリにエンコードしようとすると、パッケージで制限が発生する可能性があります。次のシナリオを考えてみましょう:
<code class="go">type T struct { Foo string // Bar represents a large stream of objects // that we don't want to load entirely into memory. Bar chan string }</code>
json.Encoder を使用してマーシャルしようとすると、サポートされていないタイプ chan 文字列が原因でエラーが発生します。
<code class="go">if err := json.NewEncoder(os.Stdout).Encode(&t); err != nil { log.Fatal(err) }</code>
このような状況では、手動で構築するとJSON文字列が必要になります。ただし、より効率的なメカニズムが望ましいです。
json.Marshaler インターフェイスが次の構造に似ていれば、エンコード プロセスはより簡単になります。
<code class="go">type Marshaler interface { MarshalJSON(io.Writer) error }</code>
残念ながら、現在、encoding/json パッケージはそのような仕組みが欠けています。したがって、組み込みパッケージのカスタマイズが必要になる場合があります。これを実現するには、encoding/json/encode.go のreflectValueQuoted 関数を変更する必要があります。具体的には、配列のケース (スライスへのフォールスルーあり) とチャネルのケースの追加に焦点を当てる必要があります。
<code class="go">// Case Array: e.WriteByte('[') n := v.Len() for i := 0; i < n; i++ { if i > 0 { e.WriteByte(',') } e.reflectValue(v.Index(i)) } e.WriteByte(']') // Case Chan: e.WriteByte('[') i := 0 for { x, ok := v.Recv() if !ok { break } if i > 0 { e.WriteByte(',') } e.reflectValue(x) i++ } e.WriteByte(']')</code>
注: チャネルのケースでは、次のような追加のチェックが必要になる場合があります。
これらの変更を実装すると、エンコード プロセス内でチャネルが配列と同様に扱われるようになります。この変更は、エンコーディング/json パッケージにパッチとして送信して、含める可能性があります。
以上がオブジェクトをメモリにロードせずに、大規模なデータ ストリームを JSON でエンコードするにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。