我尝试将多个项目序列化为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"}]
感谢任何提示!
答案 0 :(得分:4)
我会创建一个简单的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"}]
答案 1 :(得分:1)
为什么不建立IEnumerable<YourObject>
。
它不需要占用内存中的所有集合,当您将其提供给serialiazer时,它将被解析为数组。
一种简单的方法是用简单的方式替换ItemGathered
事件调用
yield return
当你