有时数组和有时是反序列化JSON对象

我使用JSON.NET库反序列化从Facebook返回的数据有点麻烦。

从简单的墙上post返回的JSON看起来像:

{ "attachment":{"description":""}, "permalink":"http://www.facebook.com/permalink.php?story_fbid=123456789" } 

返回的照片JSON看起来像:

 "attachment":{ "media":[ { "href":"http://www.facebook.com/photo.php?fbid=12345", "alt":"", "type":"photo", "src":"http://photos-b.ak.fbcdn.net/hphotos-ak-ash1/12345_s.jpg", "photo":{"aid":"1234","pid":"1234","fbid":"1234","owner":"1234","index":"12","width":"720","height":"482"}} ], 

一切都很好,我没有问题。 我现在从移动客户端遇到了一个简单的贴子,使用下面的JSON,现在反序列化失败了,只有这一个post:

 "attachment": { "media":{}, "name":"", "caption":"", "description":"", "properties":{}, "icon":"http://www.facebook.comhttp://img.dovov.comicons/mobile_app.gif", "fb_object_type":"" }, "permalink":"http://www.facebook.com/1234" 

这是我正在反序列化的类:

 public class FacebookAttachment { public string Name { get; set; } public string Description { get; set; } public string Href { get; set; } public FacebookPostType Fb_Object_Type { get; set; } public string Fb_Object_Id { get; set; } [JsonConverter(typeof(FacebookMediaJsonConverter))] public List<FacebookMedia> { get; set; } public string Permalink { get; set; } } 

没有使用FacebookMediaJsonConverter,我得到一个错误:无法将JSON对象反序列化到types'System.Collections.Generic.List`1 [FacebookMedia]'。 这是有道理的,因为在JSON中,媒体不是一个集合。

我发现这篇文章描述了类似的问题,所以我试图走下去: 反序列化JSON,有时候value是一个数组,有时候是“”(空白string)

我的转换器看起来像:

 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.StartArray) return serializer.Deserialize<List<FacebookMedia>>(reader); else return null; } 

哪些工作正常,除了我现在得到一个新的例外:

内部JsonSerializerInternalReader.cs,CreateValueInternal():反序列化对象时出现意外的标记:PropertyName

reader.Value的值是“永久链接”。 我可以清楚地看到在交换机中没有JsonToken.PropertyName的情况。

有什么我需要做不同的转换器吗? 感谢您的帮助。

JSON.NET的开发者最终帮助了项目codeplex站点。 这是解决scheme:

问题是,当它是一个JSON对象时,我没有阅读过去的属性。 这里是正确的代码:

 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.StartArray) { return serializer.Deserialize<List<FacebookMedia>>(reader); } else { FacebookMedia media = serializer.Deserialize<FacebookMedia>(reader); return new List<FacebookMedia>(new[] {media}); } } 

詹姆斯还善于为上述方法提供unit testing。

有关如何处理此案例的详细说明,请参阅“使用自定义JsonConverter修复不良的JSON结果” 。

总结一下,你可以扩展默认的JSON.NET转换器

  1. 使用问题注释属性

     [JsonConverter(typeof(SingleValueArrayConverter<OrderItem>))] public List<OrderItem> items; 
  2. 扩展转换器,即使对于单个对象,也可以返回所需types的列表

     public class SingleValueArrayConverter<T> : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { object retVal = new Object(); if (reader.TokenType == JsonToken.StartObject) { T instance = (T)serializer.Deserialize(reader, typeof(T)); retVal = new List<T>() { instance }; } else if (reader.TokenType == JsonToken.StartArray) { retVal = serializer.Deserialize(reader, objectType); } return retVal; } public override bool CanConvert(Type objectType) { return true; } } 

正如文章中提到的,这个扩展并不是完全一般的,但是如果你可以很好的获得一个列表,它就可以工作。

看看C#框架中的System.Runtime.Serialization命名空间,它会让你到达你想要的地方。

如果你愿意的话,你可以看看这个项目中的一些示例代码(不是试图插入我自己的工作,但我刚刚完成了你正在做的,但与一个不同的源api。

希望它有帮助。

我觉得你应该这样写你的课… !!!

 public class FacebookAttachment { [JsonProperty("attachment")] public Attachment Attachment { get; set; } [JsonProperty("permalink")] public string Permalink { get; set; } } public class Attachment { [JsonProperty("media")] public Media Media { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("caption")] public string Caption { get; set; } [JsonProperty("description")] public string Description { get; set; } [JsonProperty("properties")] public Properties Properties { get; set; } [JsonProperty("icon")] public string Icon { get; set; } [JsonProperty("fb_object_type")] public string FbObjectType { get; set; } } public class Media { } public class Properties { } 
Interesting Posts