web-dev-qa-db-ja.com

JSON配列を厳密に型指定された.NETオブジェクトに逆シリアル化する

サードパーティのAPIを呼び出して、1つのクラスの価値のあるデータを取得できる場合、このコードを使用してすべてが正常にデシリアライズされます

TheUser me = jsonSerializer.Deserialize(response, typeof(TheUser)) as TheUser

問題は、次のような配列であるJSON応答コンテンツをデシリアライズしようとすると発生します。

{
   "data": [
      {
         "name": "A Jones",
         "id": "500015763"
      },
      {
         "name": "B Smith",
         "id": "504986213"
      },
      {
         "name": "C Brown",
         "id": "509034361"
      }
   ]
}

「データ」メンバーの周りにカスタムラッピングクラスを使用し、そのメンバーがList<object>型である必要がある場合にのみ、シリアル化を機能させることができます。タイプがList<TheUser>である場合、JsonParser DesializeTypeメソッドからArgumentExceptionを取得します。

私はもともとこのようなラッピングタイプなしでシリアル化しようとしました

List<TheUser> freinds = jsonSerializer.Deserialize(response, typeof(List<TheUser>)) as List<TheUser>;

しかし、それは単に空のコレクションを返します。配列を厳密に型指定されたリストに逆シリアル化できるようにする必要があります。

ソース を見ているAferは、WP7の場合、Hammockは実際にはJSON解析にJson.Netを使用していません。代わりに、独自のパーサーを使用しますが、カスタムタイプにうまく対応していません。

Json.Net を直接使用すると、ラッパーオブジェクト内で厳密に型指定されたコレクションに逆シリアル化することができます。

var response = @"
    {
        ""data"": [
            {
                ""name"": ""A Jones"",
                ""id"": ""500015763""
            },
            {
                ""name"": ""B Smith"",
                ""id"": ""504986213""
            },
            {
                ""name"": ""C Brown"",
                ""id"": ""509034361""
            }
        ]
    }
";

var des = (MyClass)Newtonsoft.Json.JsonConvert.DeserializeObject(response, typeof(MyClass));

return des.data.Count.ToString();

そして:

public class MyClass
{
    public List<User> data { get; set; }
}

public class User
{
    public string name { get; set; }
    public string id { get; set; }
}

Dataプロパティを使用して追加のオブジェクトを作成するのは面倒ですが、それはJSON形式のオブジェクトが作成される方法の結果です。

ドキュメント:JSONのシリアル化と逆シリアル化

29
Matt Lacey

試してみる

List<TheUser> friends = jsonSerializer.Deserialize<List<TheUser>>(response);
11
Frank

この解決策は私にとってはうまくいくようで、「データ」を含むクラスの束をコーディングする必要があります。

public interface IDataResponse<T> where T : class
{
    List<T> Data { get; set; }
}

public class DataResponse<T> : IDataResponse<T> where T : class
{
   [JsonProperty("data")]
   public List<T> Data { get; set; }
}

最初にこれを含めるべきでした。上記を使用した方法の例を次に示します。

public List<TheUser> GetUser()
{
    var results = GetUserJson();
    var userList = JsonConvert.DeserializeObject<DataResponse<TheUser>>(results.ToString());

    return userList.Data.ToList();
} 
7
Erick Brown

これは、JSONをオブジェクトの配列に逆シリアル化するのに役立ちました:

List<TheUser> friends = JsonConvert.DeserializeObject<List<TheUser>>(response);
7
Homer

Json.NET-ドキュメント

http://james.newtonking.com/json/help/index.html?topic=html/SelectToken.htm

著者の解釈

var o = JObject.Parse(response);
var a = o.SelectToken("data").Select(jt => jt.ToObject<TheUser>()).ToList();
6
bobah75

パット、json構造は、私が説明した問題に非常に馴染みがあります ここ -エントリは1つしかありませんが、json表現をDictionary <TKey、TValue>として扱うことでした。

私が正しい場合、キーは文字列型で、List <T>の値です(Tはクラス「TheUser」を表します)

HTH

PS- Silverlight Serializer を使用してより良いシリアル化のパフォーマンスチェックアウトが必要な場合は、WP7バージョンのShamelessプラグを作成する必要があります- this に関するブログ記事を書きました

2
AwkwardCoder

この問題は、jsonがプロパティとしてユーザーのリストを持つオブジェクトを表しているためだと思われます。次のようなものにデシリアライズしてみてください:

public class UsersResponse
{
    public List<User> Data { get; set; }
}
0
Nigel Sampson