2012-02-26 29 views
9

Tôi đang cố gắng deserialize một dữ liệu json vào một lớp mô hình nhưng tôi không. Dưới đây là những gì tôi làm:Không thể deserialize JSON mảng thành loại - 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(); 
     } 
    } 

Đây là cách mô hình của tôi trông giống như:

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

Bạn có thể xem Json Tôi nhận được ở đây: http://api.worldbank.org/incomeLevels/LIC/countries?format=json

Đây là lỗi tôi nhận được:

Không thể deserialize mảng JSON thành loại 'Mvc4AsyncSample.Models.CountryModel'. Line 1, vị trí 1.

+2

Đó dường như không giống như một đại diện JSON tốt. Có lẽ sẽ tốt hơn nếu bạn sử dụng định dạng XML. – svick

+0

Vâng, tôi nghĩ vậy. Họ đặt một vật thể vào trong một mảng. Nó không nên ở đó tôi nghĩ. Có cách nào để đi lại không? – tugberk

+0

XML là rất nhiều sạch hơn, tôi muốn đi cho rằng: http://api.worldbank.org/incomeLevels/LIC/countries?format=xml –

Trả lời

17

Bạn phải viết một tùy chỉnh 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(); 
     } 
    } 

Và tag các CountryModel với chuyển đổi đó (Tôi cũng đã phải chuyển một số int để string):

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

Sau đó, bạn sẽ có thể deserialize như thế này:

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

Bạn có thể đơn giản hóa việc deserializing các thuộc tính của 'CountryModel' bằng cách sử dụng' serializer.Deserialize (reader) '? – svick

+0

Câu trả lời của svick là tốt hơn nếu bạn chỉ cần đọc, 'JsonConverter' chỉ thực sự cần thiết nếu bạn phải đi cả hai cách. –

+2

@svick Tôi nghĩ về điều đó, vấn đề là 'CountryModel' có thuộc tính, vì vậy nó được vào vòng lặp vô hạn, nó sẽ được đơn giản hóa nếu mô hình đối tượng thay đổi nhưng tôi đã cố gắng giữ cho mô hình đối tượng của mình. –

12

Điều này trông giống như một nỗ lực (không phải là rất tốt) đại diện cho XML trong JSON. JSON trông như thế này:

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

Trong khi một JSON hợp lý (mà tình cờ sẽ lập bản đồ để mô hình của bạn độc đáo) sẽ trông như thế này:

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

Nếu bạn có chắc bạn muốn sử dụng JSON (và không XML), bạn có thể làm điều đó bằng cách đầu tiên deserializing JSON thành mô hình đối tượng JSON.NET và sau đó deserialize đó vào mô hình của bạn:

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; 

Đừng quên thay đổi Id tính của bạn để string, bởi vì đó là những gì họ đang có.

+0

Đơn giản hơn nhiều so với phiên bản của tôi, tốt đẹp, không biết bạn có thể tạo ra người đọc ra khỏi các đối tượng được xây dựng trong. –

-1

Mô hình của bạn không khớp với cấu trúc JSON. Có vẻ như bạn đã bỏ lỡ 6 thuộc tính cuối cùng.

{ 
"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

điều này không ảnh hưởng đến quá trình deserialization. – tugberk

Các vấn đề liên quan