将JSON反序列化为自定义列表

时间:2016-07-13 09:58:51

标签: c# json json.net deserialization .net-4.5

我有这个json:

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

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

  • x[i][0] - 必填项 - 始终为整数
  • x[i][1] - 必填项 - 始终为字符串
  • x[i][2] - 必填项 - 始终为字符串
  • x[i][3] - 可选项 - 当它存在时,它具有以下规则:
    • x[i][3].GroupNum - 必填字段 - 始终为整数
    • x[i][3].Total - 可选字段 - 当它存在时,它是一个整数列表

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

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类永远不会被使用。我知道这是因为我在每个方法中都设置了断点,但没有一个被触发:

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:'object'不包含'Total'的定义   没有扩展方法'Total'接受第一个类型的参数   可以找到'对象'(你是否错过了使用指令或者   装配参考?)

但是,如果我只是孤立地反序列化ReportGrouping

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,所以请将其纳入您的任何答案中。

如何才能正确地反序列化Json.net,以便我可以parsed[0][3].Total[1];访问第二个总数的整数值,而无需对其进行强制转换或对其执行任何操作?

1 个答案:

答案 0 :(得分:2)

代码中有一些错误,1是该对象没有名为Total的属性,另一个是解析[0] [3]是字符串。

代码中有一些错误:

  1. 解析[0] [3]是一个字符串。通过将字符串转换为ReportGrouping来修复它。
  2. new ReportGrouping()。GroupName应根据Json命名为Group。
  3. 将已解析的[0] [3]解析为ReportingGroup后,它仍将返回一个对象,然后将i转换为ReportingGroup。即(ReportingGroup)解析[0] [3]

    git remote prune origin
  4. 并像这样使用它:

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

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

    编辑:很抱歉重复了很多次..