2014-10-19 146 views
1

我想從API反序列化Json響應。反序列化JSON C#Json.net

的數據看起來像這樣

{ 
"response": { 
    "6112": { 
     "ID": 6112, 
     "Title": "AdditionalPhotos" 
    }, 
    "5982": { 
     "ID": 5982, 
     "Title": "BikeRide" 
    }, 
    "total_records": "20", 
    "returned_count": 10, 
    "returned_records": "1-10" 

} 
} 

C#類:

public class Products 
{ 
    public class Product 
    { 
     public string Id { get; set; } 
     public string Title { get; set; } 
    } 
    public Product product { get; set; } 
} 

public class ss 
{ 
    public Dictionary<string, Products.Product> Response { get; set; } 
    public string total_records { get; set; } 

} 

序列化代碼

ss res = Newtonsoft.Json.JsonConvert.DeserializeObject<ss>(jsonData()); 

我可以得到它沒有total_records條目,低於deserializng工作一個Dictionary <string , Product>。但我無法弄清楚如何讓它起作用。這是我得到的錯誤

將值「20」轉換爲鍵入「產品+產品」時出錯。路徑「response.total_records」

我知道爲什麼我得到的錯誤,但我不能確定我怎麼能不打算在從total_records substringing下進行。我無法控制API數據。

編輯:你們是快,我仍然得到把班達

+1

屬性中的元數據是這個JSON objcet有效嗎?你有沒有嘗試http://json2csharp.com/? – 2014-10-19 19:11:45

+0

你的代碼在哪裏? – 2014-10-19 19:14:55

+0

謝謝Krzysztof,我沒有嘗試過,但我得到每個條目的個人課程。 @StephenKennedy。我知道錯誤是由於解串器試圖將「20」轉換爲它不是的產品對象而導致的。我只是無法弄清楚如何將Json反序列化爲對象的邏輯列表。 – 2014-10-19 19:23:37

回答

1

首先你JSON是不是有效的,它應該是這樣的

{ 
"response":{ 
    "6112":{ 
     "ID":"6112", 
     "Title":"Additional Photos", 
    }, 
    "5982":{ 
     "ID":"5982", 
     "Title":"Bike Ride", 
    }, 
    "total_records": "20", 
    "returned_count": "10", 
    "returned_records": "1-10", 
    } 
} 

如果你的意思是響應包含列出它應該是這樣的

{ 
"response":{ 
    "myArray": [ 
     { 
      "ID":"6112", 
      "Title":"Additional Photos", 
     }, 
     { 
      "ID":"5982", 
      "Title":"Bike Ride", 
     } 
    ], 
    "total_records": "20", 
    "returned_count": "10", 
    "returned_records": "1-10", 
    } 
} 

所以,你的代碼看起來象

public class MyArray 
{ 
    public string ID { get; set; } 
    public string Title { get; set; } 
} 

public class Response 
{ 
    public List<MyArray> myArray { get; set; } 
    public string total_records { get; set; } 
    public string returned_count { get; set; } 
    public string returned_records { get; set; } 
} 

public class RootObject 
{ 
    public Response response { get; set; } 
} 
+0

同意JSON應該看起來像第二個例子(產品作爲數組或字典),但OP表示他無法控制從API接收的數據:/ – 2014-10-19 19:37:59

+0

感謝@Mzf。斯蒂芬是正確的。沒有訪問權限。 – 2014-10-19 19:39:35

+0

@AndrewMacNaughton - 對於使用API​​-如果響應應該是JSON,但它無效,則不能使用內置的方式。如果這是一個有效的Json - 你知道API會返回多少ID嗎?它可以改變嗎? – Mzf 2014-10-19 19:44:21

-1

在我看來,這是JSON文件應該如何看起來像:

{ 
"response": { 
    "5982": { 
     "ID": 5982, 
     "Title": "BikeRide" 
    }, 
    "6112": { 
     "ID": 6112, 
     "Title": "AdditionalPhotos" 
    }, 
    "total_records": "20", 
    "returned_count": 10, 
    "returned_records": "1-10" 
} 
} 

,這是類看起來應該像

public class __invalid_type__5982 
{ 
public int ID { get; set; } 
public string Title { get; set; } 
} 

public class __invalid_type__6112 
{ 
    public int ID { get; set; } 
    public string Title { get; set; } 
} 

public class Response 
{ 
public __invalid_type__5982 __invalid_name__5982 { get; set; } 
public __invalid_type__6112 __invalid_name__6112 { get; set; } 
public string total_records { get; set; } 
public int returned_count { get; set; } 
public string returned_records { get; set; } 
} 

public class RootObject 
{ 
public Response response { get; set; } 
} 
+2

我懷疑5982和6112是否固定,他們肯定會依賴於他要求的產品? – 2014-10-19 19:35:47

+1

看起來像你剛從Json2Csharp複製粘貼。很顯然,像5982這樣的ID可以隨時改變。 – 2014-10-19 19:36:19

+0

是的,現在我們有大約300種產品... – 2014-10-19 19:41:17

0

如果你有超過API響應控制,那麼請參考Mzf的答案。

如果您無法控制API,則可能無法一次執行此特定的反序列化。你可能必須循環。

這是我的要求。

更新

修改我的方法:

創建從字典<字符串,產品>繼承的類響應,並添加元數據部件,如total_records,records_count到它的公共屬性。並創建了一個可以將JObject反序列化爲Response類的JsonConverter。

用於反串行化邏輯是非常簡單的:

  • 提取元數據部分,如total_records,records_count給變量。
  • 然後從JObject中刪除這些元數據,以使鍵值變得均勻。
  • 現在Json.net將很容易將JObject序列化爲Response對象,因爲鍵值是同質的。
  • 指定先前提取到Response對象

    public void Deserialize() 
    { 
        var json = @"{ 
         'response':{ 
         '6112':{ 
          'ID':6112, 
          'Title':'Additional Photos', 
         }, 
         '5982':{ 
          'ID':5982, 
          'Title':'Bike Ride', 
         }, 
         'total_records': '20', 
         'returned_count': 10, 
         'returned_records': '1-10', 
         } 
        }"; 
        var responseObj = Newtonsoft.Json.JsonConvert.DeserializeObject<ss>(json, new ResponseConverter()); 
    
    } 
    
    public class Response : Dictionary<string, Product> 
    { 
        public int total_records { get; set; } 
    
        public int returned_count { get; set; } 
    
        public string returned_records { get; set; } 
    } 
    
    public class Product 
    { 
        public string Id { get; set; } 
        public string Title { get; set; } 
    } 
    
    
    public class ss 
    { 
        public Response Response { get; set; } 
    } 
    
    public class ResponseConverter : Newtonsoft.Json.JsonConverter 
    { 
        private Response CreateResponse(Newtonsoft.Json.Linq.JObject jObject) 
        { 
         //preserve metadata values into variables 
         int total_records = jObject["total_records"].ToObject<int>(); 
         var returned_records = jObject["returned_records"].ToObject<string>(); 
         var returned_count = jObject["returned_count"].ToObject<int>(); 
    
         //remove the unwanted keys 
         jObject.Remove("total_records"); 
         jObject.Remove("returned_records"); 
         jObject.Remove("returned_count"); 
    
         //once, the metadata keys are removed, json.net will be able to deserialize without problem 
         var response = jObject.ToObject<Response>(); 
    
         //Assign back the metadata to response object 
         response.total_records = total_records; 
         response.returned_count = returned_count; 
         response.returned_records = returned_records; 
    
         //.. now person can be accessed like response['6112'], and 
         // metadata can be accessed like response.total_records 
    
         return response; 
        } 
    
        public override bool CanConvert(Type objectType) 
        { 
         return objectType == typeof(Response); 
        } 
    
        public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) 
        { 
         var jObject = Newtonsoft.Json.Linq.JObject.Load(reader); 
    
         Response target = CreateResponse(jObject); 
    
         serializer.Populate(jObject.CreateReader(), target); 
    
         return target; 
        } 
    
        public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) 
        { 
         throw new NotImplementedException(); 
        } 
    }