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

查看:129
本文介绍了将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/zh-CN/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?

      推荐答案

      代码中有一些错误,1是该对象没有名为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. 在将已解析的[0] [3]解析为ReportingGroup后,它仍将返回一个对象,因此之后将i强制转换为ReportingGroup. IE. (ReportingGroup)解析为[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并修复设置器.

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

      对不起,我重复了很多次..

      Sorry for repeating myself so many times..

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

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