在C#中增量式JSONparsing
我试图parsingJSON增量,即基于一个条件。
以下是我的json消息,我正在使用JavaScriptSerializer来反序列化消息。
string json = @"{"id":2, "method":"add", "params": {"object": {"name":"test" "id":"1"}, "position":"1"} }"; JavaScriptSerializer js = new JavaScriptSerializer(); Message m = js.Deserialize<Message>(json);
消息类如下所示:
public class Message { public string id { get; set; } public string method { get; set; } public Params @params { get; set; } public string position { get; set; } } public class Params { public string name { get; set; } public string id{ get; set; }
上面的代码parsing消息没有问题。 但它一次parsing整个JSON。 我只想在“方法”参数的值为“add”的情况下继续parsing。 如果不是“添加”,那么我不希望它继续parsing消息的其余部分。 有没有办法做增量parsing基于C#条件? (环境:VS 2008与.Net 3.5)
我不得不承认,我对JavaScriptSerializer并不熟悉,但是如果您打算使用JSON.net ,那么它的JsonReader
行为就像是一个DataReader
。
using(var jsonReader = new JsonTextReader(myTextReader)){ while(jsonReader.Read()){ //evaluate the current node and whether it's the name you want if(jsonReader.TokenType.PropertyName=="add"){ //do what you want } else { //break out of loop. } } }
下面是我用来parsing,加载和创build非常大的JSON文件的通用和简单的方法。 该代码现在使用几乎标准的JSON.Net库。 不幸的是,文件不是很清楚如何做到这一点,但要弄清楚也不是很难。
下面的代码假设你有大量的对象,你想序列化为JSON数组,反之亦然。 我们希望支持非常大的文件,这些文件的大小只受存储设备(而不是内存)的限制。 所以在序列化时,该方法需要IEnumerable<T>
,而反序列化它返回相同的结果。 这样你可以处理整个文件而不受内存的限制。
我已经使用这个代码文件大小为几个GB的合理性能。
//Serialize sequence of objects as JSON array in to a specified file public static void SerializeSequenceToJson<T>(this IEnumerable<T> sequence, string fileName) { using (var fileStream = File.CreateText(fileName)) SerializeSequenceToJson(sequence, fileStream); } //Deserialize specified file in to IEnumerable assuming it has array of JSON objects public static IEnumerable<T> DeserializeSequenceFromJson<T>(string fileName) { using (var fileStream = File.OpenText(fileName)) foreach (var responseJson in DeserializeSequenceFromJson<T>(fileStream)) yield return responseJson; } //Utility methods to operate on streams instead of file public static void SerializeSequenceToJson<T>(this IEnumerable<T> sequence, TextWriter writeStream, Action<T, long> progress = null) { using (var writer = new JsonTextWriter(writeStream)) { var serializer = new JsonSerializer(); writer.WriteStartArray(); long index = 0; foreach (var item in sequence) { if (progress != null) progress(item, index++); serializer.Serialize(writer, item); } writer.WriteEnd(); } } public static IEnumerable<T> DeserializeSequenceFromJson<T>(TextReader readerStream) { using (var reader = new JsonTextReader(readerStream)) { var serializer = new JsonSerializer(); if (!reader.Read() || reader.TokenType != JsonToken.StartArray) throw new Exception("Expected start of array in the deserialized json string"); while (reader.Read()) { if (reader.TokenType == JsonToken.EndArray) break; var item = serializer.Deserialize<T>(reader); yield return item; } } }
如果你看看Json.NET ,它提供了一个非caching,只能转发的JSONparsing器,它将满足你的需求。
请参阅文档中的JsonReader
和JsonTextReader
类。
你会想为JSON SAXtypes的parsing器
http://en.wikipedia.org/wiki/Simple_API_for_XML
http://www.saxproject.org/event.html
SAX在分析每个文档时引发一个事件。
在JSON中做这样的事情会(应该)非常简单,给定了JSON语法的简单性。
这个问题可能有帮助: 是否有JSON的stream媒体API?
另有链接: https : //www.p6r.com/articles/2008/05/22/a-sax-like-parser-for-json/
我目前正处于未知时间的第3小时,看着160GB的JSON被反序列化到类对象中。 我的内存使用一直悬挂在〜350MB,当我检查内存对象时,GC可以照顾所有东西。 以下是我所做的:
FileStream fs = File.Open("F:\\Data\\mysuperbig150GB.json", FileMode.Open, FileAccess.Read, FileShare.ReadWrite); StreamReader sr = new StreamReader(fs); using (JsonReader reader = new JsonTextReader(sr)) { JsonSerializer serializer = new JsonSerializer(); MyJsonToClass result = serializer.Deserialize<MyJsonToClass>(reader); }
问题是反序列化。 这160GB的数据比我的电脑一次可以处理的要大得多。
-
我用了一小段代码(这很难,甚至只是打开一个160GB的文件),并通过jsontochsarp获得了一个类结构。
-
我在auto-generated-json-tool类的自动生成结构中为大集合做了一个特定的类,而不是List的子类System.Collection.ObjectModel.ObservableCollection 。 他们都实现IEnumberable,我认为这是所有Newtsonsoft JSON解串器关心的。
-
我进去了,插入InsertItem,像这样:
protected override void InsertItem(int index, Feature item) { //do something with the item that just got deserialized //stick it in a database, etc. RemoveItem(0); }
再次,我的问题部分关于JSON的反序列化速度,但除此之外,我不能适应160GB的JSON数据到集合中。 即使收紧了,也会在几十个演出场地,比.net要满意的方式更大。
ObservableCollection上的InsertItem是我知道在反序列化发生时可以处理的唯一方法。 List.Add()不。 我知道这个解决scheme不是“优雅的”,但是我正在input这个。
这种方法的原因是什么? 如果你关心的是性能,那么它可能是“不成熟的优化”,换句话说,担心可能不存在的问题。
我强烈要求你不要担心这个细节。 build立你的应用程序,然后如果速度不够快,使用分析工具来find实际的瓶颈 – 他们可能不会在你期望的地方。
在知道这个问题之前关注性能几乎总是会导致时间浪费,代码过多。