2011-03-07 31 views
34

我在使用JSON.NET庫反序列化從Facebook返回的數據時遇到了一些麻煩。反序列化JSON有時是數組,有時是對象

的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,和反序列化失敗,現在這一個單一的差價:

"attachment": 
    { 
     "media":{}, 
     "name":"", 
     "caption":"", 
     "description":"", 
     "properties":{}, 
     "icon":"http://www.facebook.com/images/icons/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對象反序列化到類型'System.Collections.Generic.List`1 [FacebookMedia]'中。 這是有道理的,因爲在JSON中,媒體不是一個集合。

我發現這個職位描述了一個類似的問題,所以我已經試圖沿着這條路走下去:Deserialize JSON, sometimes value is an array, sometimes "" (blank 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():意外令牌反序列化對象:屬性名

reader.Value的值是「永久鏈接」。我可以清楚地看到在開關中沒有JsonToken.PropertyName的情況。

有什麼我需要在我的轉換器有不同的做法嗎?謝謝你的幫助。

回答

20

JSON.NET的開發商最終幫助上項目的CodePlex網站下面是解:。

的問題是,當它是一個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}); 
    } 
} 

詹姆斯還非常友好地爲上述方法提供單元測試。

2

看看C#框架中的System.Runtime.Serialization命名空間,它會讓你到達你想要的地方。

如果你願意,你可以在this項目(不是想插入我自己的工作,檢查了一些示例代碼,但我剛剛完成了相當多,你在做什麼,但有不同的源API。

希望幫助

+1

-1通過第三方庫推薦使用框架的內部驗證部分,並鏈接到代碼示例? – jonezy 2011-03-07 21:06:09

+0

似乎非常不尋常。 – jonezy 2011-03-07 21:06:30

+0

我不確定-1從哪裏來。我很欣賞這種迴應。我懷疑它可能來自它是一個小問題的相當重量級的解決方案(很可能是由於我自己濫用JSON.NET)。話雖如此,我將嘗試嘗試Systme.Runtime.Serialization方法,看看它是否最終能夠更好地工作。感謝您的鏈接。 – mfanto 2011-03-07 21:37:47

-2

我覺得你應該這樣寫你的課...... !!!

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 
    { 
    } 
19

關於如何處理這種情況的非常詳細的解釋可在"Using a Custom JsonConverter to fix bad JSON results"

總之,你可以擴展默認JSON.NET轉換器做

  1. 標註的屬性與問題

    [JsonConverter(typeof(SingleValueArrayConverter<OrderItem>))] 
    public List<OrderItem> items; 
    
  2. 擴展器來回報您所需類型的列表,甚至對於單個物體

    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; 
        } 
    } 
    

正如文章中提到的那樣,這個擴展並不是完全一般的,但是如果你對獲得一個清單很好,它就可以工作。

+0

絕對完美。謝謝。 – NotMe 2015-03-06 00:38:10

+0

我很困惑 - 我的WriteJson投擲不執行?我需要處理這個嗎? – nologo 2017-04-03 12:01:27

相關問題