2017-06-27 14 views
5

Json.NETを使用してNDJSON(改行で区切られたJSON)にシリアル化することはできますか? Elasticsearch APIは一括操作にNDJSONを使用しています。 .NETライブラリでこの形式がサポートされていることは何も見つかりません。Json.NETを使用してNDJSONとしてシリアル化

This answerはNDJSONをデシリアライズするためのガイダンスを提供し、それは1つが独立して、各行をシリアル化し、改行で参加するが、私は必ずしもをサポートすることを呼び出すことはありませんでしたと述べました。

string ndJson = JsonConvert.SerializeObject(value, Formatting.Indented); 

を今私はあなただけシリアライズされたオブジェクトはかなり印刷されることを望まれていないことを参照してください。

+0

このリンクはドメインを把握しています。 AWSやAzureのようなプロバイダは、数年にわたって改行文字で区切られたJSONを使用しています。 –

答えて

4

最も単純な答えは、それぞれについてCloseOutput = false設定、ライン毎に別個JsonTextWriterを使用して単一TextWriterに書き込むであろう:

public static partial class JsonExtensions 
{ 
    public static void ToNewlineDelimitedJson<T>(Stream stream, IEnumerable<T> items) 
    { 
     // Let caller dispose the underlying stream 
     using (var textWriter = new StreamWriter(stream, new UTF8Encoding(false, true), 1024, true)) 
     { 
      ToNewlineDelimitedJson(textWriter, items); 
     } 
    } 

    public static void ToNewlineDelimitedJson<T>(TextWriter textWriter, IEnumerable<T> items) 
    { 
     var serializer = JsonSerializer.CreateDefault(); 

     foreach (var item in items) 
     { 
      // Formatting.None is the default; I set it here for clarity. 
      using (var writer = new JsonTextWriter(textWriter) { Formatting = Formatting.None, CloseOutput = false }) 
      { 
       serializer.Serialize(writer, item); 
      } 
      // http://specs.okfnlabs.org/ndjson/ 
      // Each JSON text MUST conform to the [RFC7159] standard and MUST be written to the stream followed by the newline character \n (0x0A). 
      // The newline charater MAY be preceeded by a carriage return \r (0x0D). The JSON texts MUST NOT contain newlines or carriage returns. 
      textWriter.Write("\n"); 
     } 
    } 
} 

サンプルfiddle

個々のNDJSONラインは短いかもしれないが、ラインの数が多い可能性があるので、この回答は、85kbより大きな単一のストリングを割り当てる必要性を回避するストリーミング解決策を示唆している。 Newtonsoft Json.NET Performance Tipsで説明したように、このような大きな文字列はlarge object heapになり、アプリケーションのパフォーマンスが低下する可能性があります。

+0

JsonTextWriterの使用のために答えとして受け入れます。これは、ライブラリが既に提供しているものの中で最も賢明なアプローチであり、各行の新しいTextWriterを作成する他の答えのアプローチよりも顕著に優れているようです。 –

+0

実際は、上記の答えは各行にJsonTextWriterを作成する答えです。 – jlavallet

+1

@jlavallet - 'JsonConvert.SerializeObject()'は内部的に 'StringWriter'と' JsonTextWriter'の両方を作成します。詳細については、[ここ](https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/JsonConvert.cs#L647)を参照してください。個々のJSONラインは短いかもしれないが、行数は多いかもしれないので、ストリーミングソリューションは、85kbを超える単一の文字列の割り当てを避けることを提案しました[ここ](http://www.newtonsoft.com/json /help/html/Performance.htm#MemoryUsage)。 – dbc

1

あなたはこれを試みることができます。シリアライズしているオブジェクトが何らかのコレクションまたは列挙型の場合、各要素をシリアライズするだけで自分で行うことはできませんか?

StringBuilder sb = new StringBuilder(); 
foreach (var element in collection) 
{ 
    sb.AppendLine(JsonConvert.SerializeObject(element, Formatting.None)); 
} 

// use the NDJSON output 
Console.WriteLine(sb.ToString()); 
+0

一度に1行を直列化して追加するのは確かに有効ですが、私が指摘したように:これは機能性ではありません私はJson.NETからすぐに入手できます。 Json.NETがこの形式を明示的にサポートしているかどうかは疑問です。オブジェクトの配列であるNDJsonの入力タイプは何でしょうか? –

+0

Json.NETがすぐに使えるかどうかは公正な問題だと私は同意します。 – jlavallet

+0

入力の種類について - 私はNDJSON形式についてすぐに読んだものから、文脈に依存すると思います。他の「データのライン」とは別に扱うべき「1行のデータ」となるでしょう。あなたの文脈は何ですか?データの行は、いくつかのプロパティを持つ単純なオブジェクト、複数のレベルのサブオブジェクトを持つ複雑なオブジェクト、または単なる文字列にすることができます。各行に何が表示されるべきか教えてください。 – jlavallet

関連する問題