ホームページ  >  記事  >  バックエンド開発  >  オブジェクトをメモリにロードせずに、大規模なデータ ストリームを JSON でエンコードするにはどうすればよいでしょうか?

オブジェクトをメモリにロードせずに、大規模なデータ ストリームを JSON でエンコードするにはどうすればよいでしょうか?

Susan Sarandon
Susan Sarandonオリジナル
2024-10-28 04:08:30215ブラウズ

 How Can We Encode Large Data Streams in JSON Without Loading Objects in Memory?

メモリ内オブジェクトの読み込みを行わずに大規模なデータ ストリームを 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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。