2012-02-26 12 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

。おそらく、XML形式を使用した方が良いでしょう。 – svick

+0

はい、私はそう思います。彼らは配列の中に単一のオブジェクトを置く。それは私が考えるべきではないはずです。周りを回る可能性のある方法は? – tugberk

+0

XMLはすごく洗練されています。http://api.worldbank.org/incomeLevels/LIC/countries?format=xml –

答えて

17

カスタムJsonConverter記述する必要があります(私もstringにいくつかのintを切り替える必要があった)

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にタグを付ける:

[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

+0

svickの答えは読み込みが必要な方が良いですが、 'JsonConverter'は両方向に進む必要がある場合にのみ必要です。 –

+2

@svick私はそのことについて考えました。問題は、 'CountryModel'に属性があるため、無限ループに入ります。オブジェクトモデルが変更された場合は単純化されますが、オブジェクトモデルを維持しようとしていました。 –

12

これは、JSONでXMLを表現しようとする試みではないようです。合理的なJSON(つまり偶然にうまくモデルにマップする)のようになりますが

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

:JSONはこのようになりますあなたはJSONを(使用したい確信している場合

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

とないXML)、あなたが最初にJSON.NETのオブジェクトモデルにJSONをデシリアライズすることによってそれを行うと、あなたのモデルにそれをデシリアライズすることができます

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プロパティを変更することを忘れないでください。 、それはそうであるからです。

+0

私のバージョンよりもはるかに単純です、素晴らしいですが、読者が組み込みのオブジェクトから離れて作成できるかどうかは分かりませんでした。 –

-1

モデルがJSON構造と一致しません。あなたの最後の6つのプロパティが不足しているようです。良いJSON表現のように見えるしていません

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

関連する問題