c# - 使用 JSON.NET 一次序列化一组对象

标签 c# javascript .net json json.net

我尝试将多个项目序列化为 json,并将它们格式化为数组。

它是基于事件的,因为它有很多数据无法作为一个整体集合保存在内存中。但我需要将每个项目序列化到一个文件中,并将其格式化为数组。

_jsonWriter = new JsonTextWriter(new StreamWriter("Output.json")));
DataGatherer.ItemGathered += item =>
{
    _jsonSerializer.Serialize(_jsonWriter, item);
    _jsonWriter.Flush();
};

目前输出如下:

{
  "Id": 218515,
  "Name": "A"
}{
  "Id": 118647,
  "Name": "B"
}

由于序列化程序将每个项目序列化为一个对象,因此不知道它是一个数组。

那么我如何告诉 JSON.Net 序列化器将每个项目作为数组的一个项目来处理,并像这样格式化数据:

[{ "Id": 218515, "Name": "A"},{"Id": 118647,"Name": "B"}]

感谢任何提示!

最佳答案

我会创建一个简单的 JsonItemWriter 类来包装 JsonTextWriter。该类只需要跟踪是否有任何项目已写入输出。如果不是,请在写入项目之前使用内部 JsonTextWriter 将 StartArray 写入流。当外部 ItemWriter 关闭时,将 EndArray 写入流。然后更改您的事件处理程序以使用 ItemWriter 而不是 JsonTextWriter。

这是我对 JsonItemWriter 的想法:

class JsonItemWriter
{
    private JsonTextWriter innerWriter;
    private JsonSerializer serializer;

    public JsonItemWriter(JsonTextWriter innerWriter, JsonSerializer serializer)
    {
        this.innerWriter = innerWriter;
        this.serializer = serializer;
    }

    public void WriteItem(object item)
    {
        if (innerWriter.WriteState == Newtonsoft.Json.WriteState.Start)
        {
            innerWriter.WriteStartArray();
        }
        serializer.Serialize(innerWriter, item);
        innerWriter.Flush();
    }

    public void Close()
    {
        innerWriter.WriteEndArray();
        innerWriter.Close();
    }
}

然后像这样设置你的事件处理程序:

_jsonWriter = new JsonTextWriter(new StreamWriter("Output.json"));
_itemWriter = new JsonItemWriter(_jsonWriter, _jsonSerializer);

DataGatherer.ItemGathered += item =>
{
    _itemWriter.WriteItem(item);
};

这是一个简短的演示,使用模拟 DataGatherer 代替您的:

class Program
{
    static void Main(string[] args)
    {
        JsonSerializer jsonSerializer = new JsonSerializer();
        JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter("Output.json"));
        JsonItemWriter itemWriter = new JsonItemWriter(jsonWriter, jsonSerializer);

        MockDataGatherer gatherer = new MockDataGatherer();
        gatherer.ItemGathered += item =>
        {
            itemWriter.WriteItem(item);
        };

        var items = new[]
        {
            new { Id = 218515, Name = "A" },
            new { Id = 118647, Name = "B" }
        };
        gatherer.SimulateReceivingItems(items);

        itemWriter.Close();

        using (StreamReader reader = new StreamReader("Output.json"))
        {
            Console.WriteLine(reader.ReadToEnd());
        }
    }
}

class MockDataGatherer
{
    public void SimulateReceivingItems(IEnumerable<object> items)
    {
        foreach (object item in items)
        {
            ItemGathered(item);
        }
    }

    public event ItemGatheredEventHandler ItemGathered;
    public delegate void ItemGatheredEventHandler(object item);
}

这是上面的输出(注意对象现在被包裹在一个数组中):

[{"Id":218515,"Name":"A"},{"Id":118647,"Name":"B"}]

关于c# - 使用 JSON.NET 一次序列化一组对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24323498/

相关文章:

javascript - 如何在 Angular 中设置 DfxParser

c# - c# 中的 GetEnumerator() 是否返回副本或迭代原始源?

.net - 拖放到表单上(但不是表单上的 WebBrowser 控件)

c# - 如何在 visual studio 2015/中创建 C# 类图

c# - .NET中的RSA加密/解密问题

c# - 在 C# 中覆盖二元运算符

javascript - 随机播放图像 javascript/jquery

c# - 泛型方法的条件编译

javascript - QtWebEngine: "Not allowed to load local resource"for iframe,如何禁用网络安全?

c# - 从使用某些指定字符括起来的字符串中获取子字符串