使用Json.NET序列化为NDJSON

时间:2017-06-27 18:43:51

标签: c# json json.net ndjson

是否可以使用Json.NET序列化为NDJSON(Newline Delimited JSON)? Elasticsearch API使用NDJSON进行批量操作,我发现没有任何迹象表明任何 .NET库都支持这种格式。

This answer提供了反序列化NDJSON的指导,并且注意到可以单独序列化每一行并加入换行符,但我不一定称之为支持

2 个答案:

答案 0 :(得分:5)

最简单的答案是为每一行使用单独的JsonTextWriter写一个TextWriter,为每一行设置CloseOutput = false

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上,并可能随后降低应用程序性能。

答案 1 :(得分:1)

你可以试试这个:

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

但现在我发现你不仅仅希望序列化对象能够打印出来。如果您要序列化的对象是某种集合或枚举,您是否可以通过序列化每个元素来自行完成此操作?

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

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