2012-02-26 118 views
9

我想將json數據反序列化爲模型類,但是我失敗了。這是我做的:無法將JSON數組反序列化爲類型 - Json.NET

public CountryModel GetCountries() { 

     using (WebClient client = new WebClient()) { 

      var result = client.DownloadString("http://api.worldbank.org/incomeLevels/LIC/countries?format=json"); 

      var output = JsonConvert.DeserializeObject<List<CountryModel>>(result); 

      return output.First(); 
     } 
    } 

這是我的模型看起來像:

public class CountryModel 
{ 
    public int Page { get; set; } 
    public int Pages { get; set; } 
    public int Per_Page { get; set; } 
    public int Total { get; set; } 

    public List<Country> Countries { get; set; } 
} 

public class Country 
{ 
    public int Id { get; set; } 
    public string Iso2Code { get; set; } 
    public string Name { get; set; } 
    public Region Region { get; set; } 
} 

public class Region 
{ 
    public int Id { get; set; } 
    public string Value { get; set; } 
} 

你可以看到JSON的我正在這裏:http://api.worldbank.org/incomeLevels/LIC/countries?format=json

這是我的錯誤:

無法將JSON數組反序列化爲類型'Mvc4AsyncSample.Models.CountryModel'。 1號線,位置1

+2

似乎是一個好JSON表示這並不。如果你使用XML格式,可能會更好。 – svick 2012-02-26 12:12:34

+0

是的,我認爲是。他們把一個對象放在一個數組中。它不應該在我的想法。任何可能的方式來解決? – tugberk 2012-02-26 12:17:42

+0

XML是一個更清潔,我會去那裏:http://api.worldbank.org/incomeLevels/LIC/countries?format=xml – 2012-02-26 12:52:10

回答

17

你必須編寫自定義JsonConverter

public class CountryModelConverter : JsonConverter 
    { 

     public override bool CanConvert(Type objectType) 
     { 
      if (objectType == typeof(CountryModel)) 
      { 
       return true; 
      } 

      return false; 
     } 

     public override object ReadJson(JsonReader reader, Type objectType 
      , object existingValue, JsonSerializer serializer) 
     { 
      reader.Read(); //start array 
      //reader.Read(); //start object 
      JObject obj = (JObject)serializer.Deserialize(reader); 

      //{"page":1,"pages":1,"per_page":"50","total":35} 
      var model = new CountryModel(); 

      model.Page = Convert.ToInt32(((JValue)obj["page"]).Value); 
      model.Pages = Convert.ToInt32(((JValue)obj["pages"]).Value); 
      model.Per_Page = Int32.Parse((string) ((JValue)obj["per_page"]).Value); 
      model.Total = Convert.ToInt32(((JValue)obj["total"]).Value); 

      reader.Read(); //end object 

      model.Countries = serializer.Deserialize<List<Country>>(reader); 

      reader.Read(); //end array 

      return model; 
     } 

     public override void WriteJson(JsonWriter writer, object value 
      , JsonSerializer serializer) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

有了這樣的轉換器標記的CountryModel(我也不得不改用一些intstring):

[JsonConverter(typeof(CountryModelConverter))] 
    public class CountryModel 
    { 
     public int Page { get; set; } 
     public int Pages { get; set; } 
     public int Per_Page { get; set; } 
     public int Total { get; set; } 

     public List<Country> Countries { get; set; } 
    } 

    public class Country 
    { 
     public string Id { get; set; } 
     public string Iso2Code { get; set; } 
     public string Name { get; set; } 
     public Region Region { get; set; } 
    } 

    public class Region 
    { 
     public string Id { get; set; } 
     public string Value { get; set; } 
    } 

那麼你應該能夠像這樣反序列化:

var output = JsonConvert.DeserializeObject<CountryModel>(result); 
+0

難道你不能通過使用'serializer.Deserialize (reader)'來簡化對'CountryModel'的反序列化? – svick 2012-02-26 12:50:20

+0

如果您只需要閱讀,svick的答案會更好,如果您必須雙向使用,則「JsonConverter」纔是真正必需的。 – 2012-02-26 12:53:12

+2

@svick我想到了這個問題,問題是'CountryModel'有屬性,所以它進入無限循環,如果對象模型改變了,它會被簡化,但我試圖保留他的對象模型。 – 2012-02-26 12:53:39

12

這看起來像一個(不是很好)嘗試在JSON中表示XML。該JSON看起來是這樣的:

[ 
    { 
    "page": 1, 
    … 
    }, 
    [ 
    { 
     "id": "AFG", 
     "name": "Afghanistan", 
     … 
    }, 
    { 
     "id": "BDI", 
     "name": "Burundi", 
     … 
    }, 
    … 
    ] 
] 

在一個合理的JSON(即順帶映射到模型很好)應該是這樣的:

{ 
    "page": 1, 
    …, 
    "countries": [ 
    { 
     "id": "AFG", 
     "name": "Afghanistan", 
     … 
    }, 
    { 
     "id": "BDI", 
     "name": "Burundi", 
     … 
    }, 
    … 
    ] 
} 

如果您確定要使用JSON(和不是XML),則可以通過先反序列化JSON到JSON.NET的對象模型做出來,然後反序列化到模型:

var json = client.DownloadString("http://api.worldbank.org/incomeLevels/LIC/countries?format=json"); 

var array = (JArray)JsonConvert.DeserializeObject(json); 

var serializer = new JsonSerializer(); 

var countryModel = serializer.Deserialize<CountryModel>(array[0].CreateReader()); 

countryModel.Countries = serializer.Deserialize<List<Country>>(array[1].CreateReader()); 

return countryModel; 

不要忘記設置Id屬性string,因爲那就是他們。

+0

比我的版本簡單得多,很好,不知道你可以創建讀者的內置對象。 – 2012-02-26 12:50:34

-1

您的模型與JSON結構不匹配。看起來你錯過了最後6個屬性。

{ 
"id": "AFG", 
"iso2Code": "AF", 
"name": "Afghanistan", 
"region": { 
    "id": "SAS", 
    "value": "South Asia" 
}, 
"adminregion": { 
    "id": "SAS", 
    "value": "South Asia" 
}, 
"incomeLevel": { 
    "id": "LIC", 
    "value": "Low income" 
}, 
"lendingType": { 
    "id": "IDX", 
    "value": "IDA" 
}, 
"capitalCity": "Kabul", 
"longitude": "69.1761", 
"latitude": "34.5228" 

}

+7

這不影響反序列化過程。 – tugberk 2012-02-27 08:28:38

相關問題