【问题标题】:How to exclude tree nodes of a certain "type" from JSON deserialization如何从 JSON 反序列化中排除某种“类型”的树节点
【发布时间】:2018-01-12 06:13:16
【问题描述】:

假设我有一个字符串格式的节点树,我将其命名为 stringTree,其中包含 type: "Category" 的节点,我认为这些节点是不必要的:

{
    Id: 1,
    Type: "Product",
    Children: [
                  {
                      Id: 1.1,
                      Type: "Product",
                      Children: [
                                    {
                                        Id: 1.1.1,
                                        Type: "Category",
                                        Children: null
                                    },
                                    {
                                        Id: 1.1.2,
                                        Type: "Product",
                                        Children: null
                                    }
                                ]
                  },
                  {
                      Id: 1.2,
                      Type: "Category",
                      Children: null
                  }
              ]
}

请注意,这些不必要的节点可以位于树的任何级别。

我有一个包含我的树的大字符串,我将使用 JsonConvert 反序列化,如下所示:

var myTree = JsonConvert.Deserialize<Tree>(treeString);

如果它们有type = "Category",有没有办法让反序列化忽略任何节点(及其子节点)?基本上意味着这棵树会在反序列化后得到节点 1.2 和 1.1.1。

【问题讨论】:

    标签: c# json serialization tree json.net


    【解决方案1】:

    您可以使用自定义反序列化器来实现此目的,但更简单的方法是将输入字符串解析为 JTokens 的树,并过滤掉表示带有 Type == "Category" 的对象的标记:

    var jToken = JToken.Parse(treeString);
    FilterTree(jToken);
    Console.WriteLine(JsonConvert.SerializeObject(jToken, Formatting.Indented));
    
    // ..................
    
    static void FilterTree(JToken jToken)
    {
        var jArr = jToken as JArray;
        if (jArr != null)
            for (int i = jArr.Count - 1; i >= 0; i--)
            {
                if ((string)jArr[i]["Type"] == "Category")
                    jArr[i].Remove();
            }
        foreach (var child in jToken.Children())
            FilterTree(child);
    }
    

    演示:https://dotnetfiddle.net/HjVngF

    【讨论】:

      【解决方案2】:

      是否需要在反序列化过程中进行过滤?如果没有,您可以在 Tree 类中添加一个简短的递归方法,以过滤掉不需要的节点作为后处理步骤:

      public Tree Filter(string typeToRemove)
      {
          if (Type == typeToRemove)
              return null;
      
          if (Children != null)
              Children = Children.Select(c => c.Filter(typeToRemove))
                                 .Where(c => c != null)
                                 .ToList();
          return this;
      }
      

      然后像这样使用它:

      var tree = JsonConvert.DeserializeObject<Tree>(json)?.Filter("Category");
      

      小提琴:https://dotnetfiddle.net/NrvUZn

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多