Menulis JSON ke aliran tanpa buffering string di memori

Saya ingin menulis JSON ke Stream dengan membuat dokumen secara eksplisit. Misalnya:

var stream = ...;
var writer = new JsonWriter(stream);

writer.BeginArray();
{
  writer.BeginObject();
  {
    writer.String("foo");
    writer.Number(1);
    writer.String("bar");
    writer.Number(2.3);
  }
  writer.EndObject();
}
writer.EndArray();

Ini akan menghasilkan:

[
  {
    "foo": 1,
    "bar": 2.3
  }
]

Keuntungan dari pendekatan ini adalah tidak ada yang perlu di-buffer di memori. Dalam situasi saya, saya menulis cukup banyak JSON ke aliran. Solusi seperti yang ini melibatkan pembuatan semua objek Anda di memori, lalu membuat serialisasinya menjadi string besar di memori, lalu akhirnya menulis string ini ke aliran dan pengumpulan sampah, mungkin dari LOH. Saya ingin menjaga penggunaan memori saya tetap rendah, menulis elemen sambil membaca data dari aliran file/DB/dll lain.

Pendekatan semacam ini tersedia di C++ melalui library rapidjson.

Saya telah mencari-cari sedikit untuk ini dan belum menemukan solusi.


person Drew Noakes    schedule 16.08.2013    source sumber


Jawaban (1)


Ternyata saya perlu ke Google lebih lama.

JSON.NET memang mendukung ini melalui kelas JsonWriter.

Contoh saya akan ditulis:

Stream stream = ...;

using (var streamWriter = new StreamWriter(stream))
using (var writer = new JsonTextWriter(streamWriter))
{
    writer.Formatting = Formatting.Indented;

    writer.WriteStartArray();
    {
        writer.WriteStartObject();
        {
            writer.WritePropertyName("foo");
            writer.WriteValue(1);
            writer.WritePropertyName("bar");
            writer.WriteValue(2.3);
        }
        writer.WriteEndObject();
    }
    writer.WriteEndArray();
}
person Drew Noakes    schedule 16.08.2013
comment
Mengapa Anda menggunakan {, }s yang tidak diperlukan itu? - person I4V; 16.08.2013
comment
Dan mengapa saya harus menulis semua elemen secara manual secara eksplisit daripada hanya melakukan jsonSerializer.Serialize(jsonTextWriter,obj) ? - person I4V; 16.08.2013
comment
@I4V -- {} agar mudah dibaca dan bersifat opsional. Dalam contoh yang tidak sepele, mereka dapat sangat membantu. Menulis elemen secara manual adalah ide bagus jika Anda memiliki banyak sekali elemen untuk ditulis yang mengikuti format berulang sederhana. Misalnya, jika Anda menulis JSON ke aliran respons HTTP menggunakan 100.000 elemen dari SqlDataReader, menulis dengan cara ini menghindari memukul OutOfMemoryException dan, bahkan jika Anda tidak memiliki OOME, kinerja server web Anda akan jauh lebih baik. Jadi, itu tergantung pada tuntutan situasi Anda. - person Drew Noakes; 16.08.2013
comment
@ I4V, juga, dalam kasus saya, saya menggunakan pengaturan tipe pola pengunjung di mana penggunaan JsonWriter memberikan abstraksi yang bagus, memungkinkan penangan yang berbeda untuk menulis apa pun yang mereka inginkan. - person Drew Noakes; 16.08.2013
comment
@ I4V Selain itu, apakah ini pendekatan yang jauh lebih berkinerja. Serialisasi selalu membutuhkan banyak overhead. Dengan hanya menulis data yang diperlukan secara manual, Anda dapat menghindari banyak pekerjaan. Lagipula serialisasi otomatis perlu memeriksa atribut tertentu dan menganalisis struktur objek yang membutuhkan waktu lebih lama daripada menulisnya secara manual. Dalam proyek saya, saya menulis file secara manual karena bisa memakan waktu lama dengan jumlah data yang besar. Dan maaf, saya tahu thread ini sudah lama. Tapi saya pikir ini layak untuk disebutkan. - person SharpShade; 30.05.2017