【问题标题】:C# parse recursive jsonC#解析递归json
【发布时间】:2018-09-30 02:39:15
【问题描述】:

我正在尝试将 JSON 字符串解析为 C# 类。 但是我无法让它工作。

JSON 看起来像这样

{
    reports:
    {
        report:
        {
            id:"1"
            step:
            {
                id:"2"
                step:
                [
                    {
                        id:"3"
                        step:
                        [
                            {
                                id:"4"
                            },
                            {
                                id:"5"
                            }
                        ]
                    },
                    {
                        id:"6"
                        step:
                        {
                            id:"7"
                        }
                    }
                ]
            }
        }
    }
}

我做了几个类来定义结构。

private class report
{
  public mongoReports reports;
}

private class mongoReports
{
  public mongoReport report;
}

private class mongoReport
{
  public string id;
  public step step;
}

private class step
{
  public string id = "";
}

private class step
{
  public string id = "";
  public step step;
}

private class step
{
  public string id = "";
  public list<step> step;
}

问题在于 step 可以有 3 个定义。 1 没有和 step 属性, 1 步的类型为“步” 1 其中 step 是“step”类型的对象列表。

我怎样才能制作一个适合所有这些结构的合适的“步骤”类?

【问题讨论】:

  • 将 json 复制到剪贴板,然后在 VS 中:“Edit”、“Paste Special”、“Paste JSON As Classes”;工作完成
  • @MarcGravell 我猜这是动态的层次结构,所以从长远来看,一次性 JSON-to-C# 操作无济于事。

标签: c# json mongodb recursion


【解决方案1】:

如果你想看看的话,我已经在 dotnetfiddle 上做了一些原型。

JSON Recursive Example

基本上,您可以有一个实现“步骤”列表的“根”步骤。然后每个步骤都有一个相关的步骤列表。然后这两个列表都由 SingleOrArrayConverter 解析,并根据是否有 0,1 或 n 个步骤,列表将填充适当的步骤对象。当自定义转换器在 JSON 源中遇到新的 Step 对象时,它会被 JSON 反序列化器递归调用。

类结构如下所示:

public class Rootobject
{
    public Reports reports { get; set; }
}

public class Reports
{
    public Report report { get; set; }
}

public class Report
{
    public string id { get; set; }
    public RootStep step { get; set; }
}

public class RootStep
{
    public string id { get; set; }
    [JsonConverter(typeof(SingleOrArrayConverter<Step>))]
    public List<Step> step { get; set; }
}

public class Step
{
    public string id { get; set; }
    [JsonConverter(typeof(SingleOrArrayConverter<Step>))]
    public List<Step> step { get; set; }
}

这样做的好处在于您将直接处理结果对象中的“步骤”类,而不是动态对象或进一步的 JSON 反序列化。

缺点是反序列化的 JSON 与输入的 JSON 不完全匹配。我不确定这对您来说是否是一个问题,但如果是这样,那么您可以考虑修改 WriteJson 方法以适应它。

希望对您有所帮助。

【讨论】:

  • 感谢您提供此示例,它似乎工作得很好。
【解决方案2】:

如果不能使用像 Newtonsoft JSON 这样的库,您可以考虑将解析分解为一组子解析器。即使是接受字符串的构造函数,也期望它是 JSON。所以你会打电话

new reports(myJSON)

而report(string json) 会依次调用new

mongoReports(reportJSON)

最终你会得到一个如下所示的调用:

new step(@"{
  id:\"4\"
}"

如果您不想将其嵌入到类本身中,您可以使用工厂模式执行相同的操作,并将 reports reportsCreator(string myJSON) 降至 public stepCreator(string stepJSON)

但这可能需要更改您的小班的“曝光”(我不记得官方术语 - 公共/私人/受保护)。

【讨论】:

    猜你喜欢
    • 2020-05-31
    • 2011-05-05
    • 2012-01-17
    • 2012-08-11
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    • 1970-01-01
    相关资源
    最近更新 更多