【问题标题】:C# deserialize multiple JSON collections into a single List<T>C# 将多个 JSON 集合反序列化为单个 List<T>
【发布时间】:2017-08-16 12:36:12
【问题描述】:

我从 web api 获取相同对象的集合。 然后我想将 JSON 反序列化为单个列表

JSON如下:

{
  "Liverpool": [
    {
      "playerId": "LIV01",
      "name": "Adam Llana",
      "position": "Midfielder"
    },
    {
      "playerId": "LIV02",
      "name": "Daniel Sturridge",
      "position": "Forward"
    }
  ],
  "ManchesterUnited": [
    {
      "playerId": "MNU01",
      "name": "Daley Blind",
      "position": "Defender"
    },
    {
      "playerId": "MNU02",
      "name": "Romelu Lukaku",
      "position": "Forward"
    }
  ],
  "Arsenal": [
    {
      "playerId": "ARS01",
      "name": "Petr Cech",
      "position": "Goalkeeper"
    },
    {
      "playerId": "ARS02",
      "name": "Santi Cazorla",
      "position": "Midfielder"
    }
  ]
}

由于我对集合名称不感兴趣,因此我希望能够做到以下几点:

public class Player
{
    public string playerId { get; set; }
    public string name { get; set; }
    public string position { get; set; }
}

List<Player> cards = JsonConvert.DeserializeObject<List<Player>>(jsonContent);      

这不起作用并产生错误。

无法反序列化当前 JSON 对象(例如 {\"name\":\"value\"}) 进入类型 'System.Collections.Generic.List`1[Player]' 因为类型 需要一个 JSON 数组(例如 [1,2,3])才能正确反序列化。修理 此错误将 JSON 更改为 JSON 数组(例如 [1,2,3])或 更改反序列化类型,使其成为普通的 .NET 类型(例如 不是像整数这样的原始类型,不是像数组这样的集合类型 或列表)可以从 JSON 对象反序列化。 JsonObjectAttribute 也可以添加到类型中以强制它 从 JSON 对象反序列化。

有没有什么方法可以使用 Newtonsoft.Json 来实现这一点?

【问题讨论】:

    标签: c# json deserialization


    【解决方案1】:

    由于团队名称可变,您需要反序列化为Dictionary&lt;string, List&lt;Player&gt;&gt;。从那里对字典的值使用SelectMany 来获取玩家

    public class Player
    {
        public string playerId { get; set; }
        public string name { get; set; }
        public string position { get; set; }
    }
    
    var teams = JsonConvert.DeserializeObject<Dictionary<string, List<Player>>>(jsonContent);
    List<Player> players = teams.SelectMany(kvp => kvp.Value).ToList();
    

    【讨论】:

      【解决方案2】:

      您想要的是将该对象反序列化为字典:

      var teams = JsonConvert.DeserializeObject<Dictionary<string, List<Player>>>(jsonContent);
      

      原始对象不是数组,因此将其反序列化为数组或List&lt;T&gt; 是没有意义的

      以后,如果你只想要球员名单而不关心俱乐部名称,那么只需使用 LINQ 的 SelectMany 来展平字典:

      var allPlayers = teams.SelectMany(entry => entry.Value);
      

      【讨论】:

        【解决方案3】:

        如果您现在只是尝试为玩家创建一个对象,它将无法正常工作,因为团队名称是唯一的。您要反序列化的类应如下所示:

        public class Teams
        {
            public Liverpool[] Liverpool { get; set; }
            public Manchesterunited[] ManchesterUnited { get; set; }
            public Arsenal[] Arsenal { get; set; }
        }
        
        public class Liverpool
        {
            public string playerId { get; set; }
            public string name { get; set; }
            public string position { get; set; }
        }
        
        public class Manchesterunited
        {
            public string playerId { get; set; }
            public string name { get; set; }
            public string position { get; set; }
        }
        
        public class Arsenal
        {
            public string playerId { get; set; }
            public string name { get; set; }
            public string position { get; set; }
        }
        

        现在您可以直接将数据反序列化为该对象。

        Teams teams = JsonConvert.DeserializeObject<Teams>(jsonContent); 
        

        它们是顶部文件菜单编辑选项中称为选择性粘贴的选项,此选项可让您创建模仿的类json 或 xml 的属性。

        【讨论】:

        • 如果 OP 有 1000 个团队要反序列化怎么办?如果事先不知道他们的名字怎么办?如果将来在Player 中添加新属性怎么办?
        • 是的,这是这个实现的一个问题。感谢您强调这个问题。
        猜你喜欢
        • 2010-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-07
        • 1970-01-01
        相关资源
        最近更新 更多