【问题标题】:Deserializing JSON array into strongly typed .NET object将 JSON 数组反序列化为强类型的 .NET 对象
【发布时间】:2011-05-12 14:20:27
【问题描述】:

当我可以调用第 3 方 api 并取回单个类的数据时,一切都可以使用此代码进行反序列化

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

但这只会给我一个空集合。当然,我必须能够将数组反序列化为强类型列表。

【问题讨论】:

  • 我也有同样的问题;如果您将response 反序列化为dynamic var 而不是TheUser,那么deserialized.data 可以作为JArray 使用——知道是否可以将其转换为List&lt;something&gt;
  • 看来你应该可以(link)。

标签: c# windows-phone-7 json.net hammock


【解决方案1】:

在查看the source 之后,WP7 Hammock 实际上并没有使用 Json.Net 进行 JSON 解析。相反,它使用自己的解析器,不能很好地处理自定义类型。

如果直接使用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 格式对象的构造方式的结果。

文档:Serializing and Deserializing JSON

【讨论】:

  • 在 Hammock 中更改 DeSerializer 非常容易。创建一个实现 Hammock.Serialization.IDeserializer 接口的类。然后将该类设置为 RestClient 上的 Deserializer。
  • 我同意添加额外的对象有点烦人,因此我的解决方案如下。我的方法也让您不必像在 var des = (MyClass)... 行中那样处理。不确定这个或我的解决方案是否比另一个更好,只是不想添加额外的 Data 对象,我通常会尽量避免类型转换。
  • 首先执行Json.Parse(jsonString),然后执行JsonConvert.DeserializeObject(parsedJson["data"]).ToString()) 以最终获得User 的列表,性能和理智如何? ;-)
  • 我多次阅读这个线程来调试同一个问题。就我而言,我必须以正确的格式获取 JSON 以供 JSON.Net 包处理。我会向面临类似问题的其他人提供的是使用 TraceWriter 作为错误消息帮助突出显示我在 JSON 文件中没有看到的错误。
【解决方案2】:

试试

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

【讨论】:

  • 这不会编译,但是这不只是一种不同的调用风格会导致相同的底层方法以相同的方式被调用吗?我看不出这将如何解决我的问题
  • 这对我有用:List&lt;TheUser&gt; friends = JsonConvert.DeserializeObject&lt;List&lt;TheUser&gt;&gt;(response);
  • 谢谢!这使我能够反序列化对象数组,而无需将它们包装在容器对象中。
  • 我喜欢 Homer 的解决方案,我同意它比我的解决方案更简洁一些,因为如果您不想从任何东西继承,它不需要拥有父类或必须实现接口。 -埃里克
【解决方案3】:

这对我有用,可以将 JSON 反序列化为对象数组:

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

【讨论】:

    【解决方案4】:

    这个解决方案似乎对我有用,并且不必编写一堆带有“数据”的类。

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

    【讨论】:

      【解决方案5】:

      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】:

        Pat,对于我描述的问题here,json 结构看起来非常熟悉 - 我的答案是将 json 表示视为 Dictionary,即使只有 1 个条目。

        如果我是正确的,您的密钥是字符串类型和 List 的值,其中 T 表示类“TheUser”

        HTH

        PS - 如果你想要更好的序列化性能检查使用 Silverlight Serializer,你需要构建一个 WP7 版本,无耻插件 - 我写了一篇关于 this 的博客文章

        【讨论】:

          【解决方案7】:

          我喜欢这种方法,它对我来说很直观。

          using (var webClient = new WebClient())
              {
                    var response = webClient.DownloadString(url);
                    JObject result = JObject.Parse(response);
                    var users = result.SelectToken("data");   
                    List<User> userList = JsonConvert.DeserializeObject<List<User>>(users.ToString());
              }
          

          【讨论】:

          • 非常有用的建议!谢谢。
          【解决方案8】:

          我怀疑问题是因为 json 表示一个以用户列表作为属性的对象。尝试反序列化为:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-10-15
            • 1970-01-01
            • 1970-01-01
            • 2013-10-30
            • 1970-01-01
            • 2017-12-19
            • 2013-02-17
            • 2017-01-28
            相关资源
            最近更新 更多