【问题标题】:JSON.NET how to remove nodesJSON.NET 如何删除节点
【发布时间】:2012-07-25 10:40:19
【问题描述】:

我有一个像下面这样的 json:

{
  "d": {
    "results": [
      {
        "__metadata": {
        },
        "prop1": "value1",
        "prop2": "value2",
        "__some": "value"
      },
      {
        "__metadata": {
        },
        "prop3": "value1",
        "prop4": "value2",
        "__some": "value"
      },
    ]
  }
}

我只想将此 JSON 转换为不同的 JSON。我想从 JSON 中去除“_metadata”和“_some”节点。我正在使用 JSON.NET。

【问题讨论】:

  • 我没有使用 C# 的经验,但我假设您可以简单地解析 JSON,从结果数据结构中删除它们的键,然后再次将其转换回 JSON。
  • 我可以做到,但我正在寻找 JSON.NET 的方法。

标签: c# json json.net jsonpath


【解决方案1】:

如果您有一个带有 JToken 而不是 JObjects 的 JArray,则此答案适用:

这是一个例子:

string json = "[null, null, \"x\", null, null, null, 0,[],[[\"x\"], null,[0],[\"x\"]]]";

    JArray array = JArray.Parse(json);

    // Keep first 3 elements, remove the rest
    int max = array.Count;
    for (int i = 0; i < max - 3; i++)
    {
        JToken elem = array[3];
        array.Remove(elem);
    }

    json = array.ToString(Newtonsoft.Json.Formatting.None);

    Console.WriteLine(json);

【讨论】:

    【解决方案2】:

    基于@[Mohamed Nuur] 的回答,我将其更改为我认为效果更好的扩展方法:

     public static JToken RemoveFields(this JToken token, string[] fields)
        {
            JContainer container = token as JContainer;
            if (container == null) return token;
    
            List<JToken> removeList = new List<JToken>();
            foreach (JToken el in container.Children())
            {
                JProperty p = el as JProperty;
                if (p != null && fields.Contains(p.Name))
                {
                    removeList.Add(el);
                }
                el.RemoveFields(fields);
            }
    
            foreach (JToken el in removeList)
            {
                el.Remove();
            }
    
            return token;
        }
    

    这里是单元测试:

    [TestMethod]
         public void can_remove_json_field_removeFields()
         {
            string original = "{\"d\":{\"results\":[{\"__metadata\":{},\"remove\":\"done\",\"prop1\":\"value1\",\"prop2\":\"value2\",\"__some\":\"value\"},{\"__metadata\":{},\"prop3\":\"value1\",\"prop4\":\"value2\",\"__some\":\"value\"}],\"__metadata\":{\"prop3\":\"value1\",\"prop4\":\"value2\"}}}";
            string expected = "{\"d\":{\"results\":[{\"prop1\":\"value1\",\"prop2\":\"value2\",\"__some\":\"value\"},{\"prop3\":\"value1\",\"prop4\":\"value2\",\"__some\":\"value\"}]}}";
            string actual = JToken.Parse(original).RemoveFields(new string[]{"__metadata", "remove"}).ToString(Newtonsoft.Json.Formatting.None);
            Assert.AreEqual(expected, actual);
         }
    

    【讨论】:

    • 很好的解决方案,经过测试和使用
    【解决方案3】:

    我刚刚反序列化为 JObject 并递归地循环遍历它以删除不需要的字段。感兴趣的朋友可以看看这里的功能。

    private void removeFields(JToken token, string[] fields)
    {
        JContainer container = token as JContainer;
        if (container == null) return;
    
        List<JToken> removeList = new List<JToken>();
        foreach (JToken el in container.Children())
        {
            JProperty p = el as JProperty;
            if (p != null && fields.Contains(p.Name))
            {
                removeList.Add(el);
            }
            removeFields(el, fields);
        }
    
        foreach (JToken el in removeList)
        {
            el.Remove();
        }
    }
    

    【讨论】:

    • 谢谢!我需要那个。现在我可以对我的 JArray 的 Children 集合执行 Foreach 以删除我想要的所有属性。
    • 这对我很有帮助 - 我想记录 JSON 数据,其中敏感字段替换为数据长度。我能够获取并设置 p.Value。
    【解决方案4】:

    我将创建一个仅包含所需信息的新数据结构,并从第一个数据结构中复制数据。通常这是最简单的方法。只是一个想法。

    【讨论】:

    • 但我不知道数据会是什么。我想编写一个通用函数,它将接受一个 JSON 字符串和一个要排除的属性列表(可能是 xpath 类型?)并返回一个没有排除属性的新 JSON 字符串。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多