我正在使用 Json.NET 反序列化由 iOS 客户端(使用 Monotouch)上的 API 服务器发送的 json 文件。我有一个非常奇怪的问题,因为有时反序列化会因随机异常而失败。我之前没有任何问题,我认为它是从 json 文件变大开始的。发生这种情况时,我只是要求应用程序再试一次,并且在随机次数(并随机选择不同的异常)之后,反序列化最终会无缘无故地工作。
以下是我得到的不同例外:
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
这是我用于反序列化的几行代码:
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);
}
}
}
}
它在 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;
}
}
关于我的 JsonConverter 的一些解释:服务器在 JSON 文件上发送的对象可能会根据“type_id”值而改变。JsonConverter 尝试读取 type_id 并根据它返回正确的对象。
我现在的解决方法是读取字符串中的整个流,然后将其传递给 json 反序列化器,但它在 iOS 上肯定更慢(更多 CPU 消耗)。
我不知道为什么有时它有效,有时无效。