Randoms errors while deserializing json.net via WebRequest

I use Json.NET to deserialize json files sent by the API server on the iOS client (with Monotouch). I have a very strange problem, because sometimes deserialization fails with randoms exceptions. I had no problems before, and I think it started from the moment the json files got bigger. When this happens, I just ask the application to try again and after a random number of times (and randoms have different exceptions), deserialization finally works, for no reason.

Here are the various exceptions I received:

2013-02-12 19:14:58.307 client_ios[2176:4303] Failed to deserialize: Unexpected end of content while loading JObject. at Newtonsoft.Json.Linq.JContainer.ReadTokenFrom (Newtonsoft.Json.JsonReader r) [0x00000] in <filename unknown>:0 at Newtonsoft.Json.Linq.JObject.Load (Newtonsoft.Json.JsonReader reader) [0x00000] in <filename unknown>:0 at shared.api.NotificationConverter.ReadJson (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Object existingValue, Newtonsoft.Json.JsonSerializer serializer) [0x00000] in /Users/xxx/Projects/xxx/shared/src/api/Notification.cs:23 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueNonProperty (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract) [0x00000] in <filename unknown>:0 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList (IWrappedCollection wrappedList, Newtonsoft.Json.JsonReader reader, System.String reference, Newtonsoft.Json.Serialization.JsonArrayContract contract) [0x00000] in <filename unknown>:0 Failed to deserialize: Unterminated string. Expected delimiter: ". Line 2530, position 69. at Newtonsoft.Json.JsonTextReader.ReadStringIntoBuffer (Char quote) [0x00000] in <filename unknown>:0 at Newtonsoft.Json.JsonTextReader.ParseString (Char quote) [0x00000] in <filename unknown>:0 at Newtonsoft.Json.JsonTextReader.ParseValue (Char currentChar) [0x00000] in <filename unknown>:0 at Newtonsoft.Json.JsonTextReader.ReadInternal () [0x00000] in <filename unknown>:0 at Newtonsoft.Json.JsonTextReader.Read () [0x00000] in <filename unknown>:0 at Newtonsoft.Json.Linq.JContainer.ReadContentFrom (Newtonsoft.Json.JsonReader r) [0x00000] in <filename unknown>:0 at Newtonsoft.Json.Linq.JContainer.ReadTokenFrom (Newtonsoft.Json.JsonReader r) [0x00000] in <filename unknown>:0 at Newtonsoft.Json.Linq.JObject.Load (Newtonsoft.Json.JsonReader reader) [0x00000] in <filename unknown>:0 at shared.api.NotificationConverter.ReadJson (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Object existingValue, Newtonsoft.Json.JsonSerializer serializer) [0x00000] in /Users/xxx/Projects/xxx/shared/src/api/Notification.cs:23 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueNonProperty (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract) [0x00000] in <filename unknown>:0 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList (IWrappedCollection wrappedList, Newtonsoft.Json.JsonReader reader, System.String reference, Newtonsoft.Json.Serialization.JsonArrayContract contract) [0x00000] in <filename unknown>:0 

Here are some lines that I use for deserialization:

 using (WebResponse webResponse = requestWeb.GetResponse()) { using (Stream responseStream = webResponse.GetResponseStream()) { using (StreamReader streamReader = new StreamReader(responseStream)) { using (JsonReader jsonReader = new JsonTextReader(streamReader)) { JsonSerializer serializer = new JsonSerializer(); serializer.Converters.Add(creator); rsp = serializer.Deserialize<SimpleServerResponse>(jsonReader); } } } } 

Crash in JObject.Load (reader):

 public class NotificationConverter : JsonConverter { public override bool CanConvert(Type objectType) { return typeof(ANotification).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject jobject = JObject.Load(reader); object target = null; JToken token = jobject["type_id"]; if (token != null) { int id = token.ToObject<int>(); switch (id) { case ANotification.STORY_INVITE: target = new Notification<Moment>(); break; case ANotification.STORY_CONTENT_ADDED: target = new Notification<Moment>(); break; case ANotification.STORY_LIKE: target = new Notification<Moment>(); break; case ANotification.PICTURE_COMMENTED: target = new Notification<PictureMomentPair>(); break; case ANotification.PICTURE_LIKED: target = new Notification<PictureMomentPair>(); break; case ANotification.USER_FOLLOW: target = new Notification<User>(); break; default: break; } serializer.Populate(jobject.CreateReader(), target); } return target; } } 

Some explanation of my JsonConverter: objects sent by the server in the JSON file may change depending on the value of "type_id". JsonConverter will try to read type_id and return the correct object depending on it.

My workaround so far is to read the entire stream in a string and then pass it to json deserializer, but it is definitely slower on iOS (more CPU consumed).

I donโ€™t know why sometimes it works, and sometimes not.

+4
source share

All Articles