将 JSON 反序列化为自定义列表 [英] Deserialize JSON into custom list

查看:36
本文介绍了将 JSON 反序列化为自定义列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个 json:

var x = [
    [99,"abc","2dp",{"GroupNum": 0,"Total":[4, 1]}],
    [7,"x","date"],
    [60,"x","1dp",{"GroupNum": 1}],
    ...
]

存在以下规则(让 i 指代内部列表索引):

The following rules exist (let i refer to the inner list index):

  • x[i][0] - 必填项 - 始终为整数
  • x[i][1] - 必填项 - 总是一个字符串
  • x[i][2] - 必填项 - 总是一个字符串
  • x[i][3] - 可选项目 - 当它存在时,它具有以下规则:
    • x[i][3].GroupNum - 必填字段 - 始终为整数
    • x[i][3].Total - 可选字段 - 当它存在时,它是一个整数列表
    • x[i][0] - mandatory item - always an integer
    • x[i][1] - mandatory item - always a string
    • x[i][2] - mandatory item - always a string
    • x[i][3] - optional item - when it exists then it has the following rules:
      • x[i][3].GroupNum - mandatory field - always an integer
      • x[i][3].Total - optional field - when it exists then it is a list of integers

      所以我为这些规则创建了以下类:

      So I have created the following classes for these rules:

      public class ReportTemplateField : System.Collections.CollectionBase
      {
          public object this[int index]
          {
              get
              {
                  switch (index)
                  {
                      case 0:
                          return (int)List[index];
                      case 1:
                      case 2:
                          return (string)List[index];
                      case 3:
                          return (ReportGrouping)List[index];
                      default:
                          throw new System.ArgumentOutOfRangeException("Class ReportTemplateField only contains 4 items");
                  }
              }
              set
              {
                  switch (Count)
                  {
                      case 0:
                          List[index] = unchecked((int)value);
                          break;
                      case 1:
                      case 2:
                          List[index] = (string)value;
                          break;
                      case 3:
                          List[index] = (ReportGrouping)value;
                          break;
                      default:
                          throw new System.ArgumentOutOfRangeException("Class ReportTemplateField may only contain 4 items");
                  }
              }
          }
      
          public void Add(object item)
          {
              switch (Count)
              {
                  case 0:
                      List.Add(unchecked((int)item));
                      break;
                  case 1:
                  case 2:
                      List.Add((string)item);
                      break;
                  case 3:
                      List.Add((ReportGrouping)item);
                      break;
                  default:
                      throw new System.ArgumentOutOfRangeException("Class ReportTemplateField may only contain 4 items");
              }
          }
      }
      
      public class ReportGrouping
      {
          public int GroupNum { get; set; }
          public List<int> Total { get; set; }
      }
      

      然而,当我尝试使用 json.net 反序列化时,ReportTemplateField 类永远不会被使用.我知道这一点是因为我在每个方法中都设置了断点,但没有一个被触发:

      However, when I attempt to deserialize using json.net, the ReportTemplateField class never gets used. I know this because I have put breakpoints in every method and none of them get triggered:

      string json = "[[99,"abc","2dp",{"GroupNum": 0,"Total":[4, 1]}],[7,"x","date"],[60,"x","1dp",{"GroupNum": 1}]]";
      List<ReportTemplateField> parsed = JsonConvert.DeserializeObject<List<ReportTemplateField>>(json);
      int Total01 = parsed[0][3].Total[1];
      

      给我这个错误:

      错误 CS1061:对象"不包含总计"的定义和没有接受第一个类型参数的扩展方法Total"可以找到对象"(您是否缺少 using 指令或汇编参考?)

      error CS1061: 'object' does not contain a definition for 'Total' and no extension method 'Total' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

      但是,如果我只是单独反序列化 ReportGrouping,它会起作用:

      However it works if I just deserialize the ReportGrouping in isolation:

      string json2 = "{"GroupNum": 0,"Total":[4, 1]}";
      ReportGrouping parsed2 = JsonConvert.DeserializeObject<ReportGrouping>(json2);
      parsed2.Total[1]; // 1
      

      所以问题在于 ReportTemplateField 类.也许我不应该从 System.Collections.CollectionBase 继承?我基本上按照此演练进行了一些修改 - https://msdn.microsoft.com/en-us/library/xth2y6ft(v=vs.71).aspx 但它确实说文档可能已经过时.我使用的是 .NET 4.5,所以请将其纳入您的任何答案中.

      So the problem lies with the ReportTemplateField class. Maybe I shouldn't be inheriting from System.Collections.CollectionBase? I basically followed this walkthough with some modifications - https://msdn.microsoft.com/en-us/library/xth2y6ft(v=vs.71).aspx but it does say that the documentation may be outdated. I'm using .NET 4.5 so please factor that into any your answers.

      我怎样才能让 Json.net 正确反序列化,这样我就可以去 parsed[0][3].Total[1]; 访问第二个总数的整数值,而不需要需要投射它或对它做任何事情吗?

      How can I get Json.net to deserialize correctly, so that I can just go parsed[0][3].Total[1]; to access the integer value of the second total without needing to cast it or do anything to it at all?

      推荐答案

      代码中有几个错误,一是对象没有名为 Total 的属性,二是 parsed[0][3] 是一个字符串.

      There is a few errors in the code, 1 is that object does not have a property called Total and another is that parsed[0][3] is a string.

      您的代码中有一些错误:

      You have a few errors in the code:

      1. parsed[0][3] 是一个字符串.通过将字符串转换为 ReportGrouping 来修复它.
      2. new ReportGrouping().GroupName 应根据 Json 命名为 Group.
      3. 在您将 parsed[0][3] 解析为 ReportingGroup 后,它仍会返回一个对象,因此之后将 i 转换为 ReportingGroup.IE.(ReportingGroup)parsed[0][3].

      1. parsed[0][3] is a string. Fix it by converting the string into a ReportGrouping.
      2. new ReportGrouping().GroupName should be named Group according to Json.
      3. After you have parsed parsed[0][3] into a ReportingGroup it will still return a object, so cast i into a ReportingGroup afterwards. I.e. (ReportingGroup)parsed[0][3].

      get
      {
          switch (index)
          {
              case 0:
                  return (int)List[index];
              case 1:
              case 2:
                  return (string)List[index];
              case 3:
                  return JsonConvert.DeserializeObject<ReportGrouping>(List[index].ToString());
              default:
                  throw new System.ArgumentOutOfRangeException("Class ReportTemplateField only contains 4 items");
          }
      }
      

    • 并像这样使用它:

      List<ReportTemplateField> parsed = JsonConvert.DeserializeObject<List<ReportTemplateField>>(json);
      ReportGrouping group = (ReportGrouping)parsed[0][3];
      

      不要忘记将 GroupName 重命名为 Group 并修复 setter.

      Dont forget to rename GroupName into Group and to fix the setter.

      抱歉我重复了这么多次..

      Sorry for repeating myself so many times..

      这篇关于将 JSON 反序列化为自定义列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆