如何按值查找json令牌,然后删除令牌 [英] How to find json token by value and then delete the token

查看:83
本文介绍了如何按值查找json令牌,然后删除令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,我在C#中有一个像这样的json:

I have, for example, a json like this in C# :

{
"Harry.firstName": "Harry",
"Harry.lastName": "Birimirski",
"Harry.recordTitle": "My title",
"Harry.SomeRepeatable": [{
        "GUID": "9dd8c7bb-64e1-452b-90d5-db2b6e505492",
        "NestedRepetable": [{
                "GUID": "05aa2161-fcc2-45a6-b0b7-8749d94a2e61",
                "nestedText": "Nested first"
            },
            {
                "GUID": "dfd67eeb-703b-4cc4-9321-b6a39084e687",
                "nestedText": "Nested first 2"
            }
        ],
        "name": "First"
    },
    {
        "GUID": "3318e544-1be8-4795-9bab-fa05de79cf46",
        "NestedRepetable": [{
            "GUID": "c1b60869-7c75-4af4-8037-be26aeca7939",
            "nestedText": "Nested second"
        }],
        "name": "Second"
    }
]
}

我想按值从NestedRepetable数组中删除项目. 例如,删除包含GUID:05aa2161-fcc2-45a6-b0b7-8749d94a2e61的元素,所需的结果将类似于:

And I would like to remove item from NestedRepetable array by value. For example remove element that contains GUID: 05aa2161-fcc2-45a6-b0b7-8749d94a2e61, desired result will looks like :

{
"Harry.firstName": "Harry",
"Harry.lastName": "Birimirski",
"Harry.recordTitle": "My title",
"Harry.SomeRepeatable": [{
        "GUID": "9dd8c7bb-64e1-452b-90d5-db2b6e505492",
        "NestedRepetable": [
            {
                "GUID": "dfd67eeb-703b-4cc4-9321-b6a39084e687",
                "nestedText": "Nested first 2"
            }
        ],
        "name": "First"
    },
    {
        "GUID": "3318e544-1be8-4795-9bab-fa05de79cf46",
        "NestedRepetable": [{
            "GUID": "c1b60869-7c75-4af4-8037-be26aeca7939",
            "nestedText": "Nested second"
        }],
        "name": "Second"
    }
]
}

我已经在Json.NET的帮助下尝试了几件事,但是我做不到. 请记住,整个JSON结构是动态的.我唯一知道的是这种情况下的字段名称(GUID)和应删除的字段中的值.

I've tried a couple of things with the help of Json.NET, but I cannot do it. Keep in mind that the whole JSON structure is dynamic. The only thing that I know is the field name (GUID) in this case and the value in the field, that should be removed.

我已尝试按照

I've tried to do it in that way described in this question, But they are using a hardcoded path of the json. That's not my case.

我使用了以下代码:

        private JToken RemoveFields(JToken token, string fieldValue)
    {
        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))
            {
                if (p.Value.ToString() == fieldValue)
                {
                    removeList.Add(el);

                    //try to remove the whole thing, not only GUID field ..
                    //removeList.Add(el.Parent);

                }
            }

            RemoveFields(el, fieldValue);
        }

        foreach (JToken el in removeList)
        {
            el.Parent.Remove();
            return token;
        }

        return token;
    }

但是我收到以下错误:

集合已修改;枚举操作可能无法执行"

Collection was modified; enumeration operation may not execute"

可能是因为我正在尝试删除父元素.

Probably because I'm trying to remove the parent element.

推荐答案

您正在尝试查找和删除符合以下条件的对象:

You are attempting to find and remove objects that match the following criteria:

  1. 名为"NestedRepetable"
  2. 的数组属性包含的所有对象
  3. 具有一个具有特定值的名为"GUID"的属性.
  1. All objects contained by an array property named "NestedRepetable"
  2. that have a property named "GUID" with a specific value.

最简单的方法是使用 JToken.SelectTokens() 带有 JSONPath查询:

The easiest way to do this will be to use JToken.SelectTokens() with a JSONPath query:

var value = "05aa2161-fcc2-45a6-b0b7-8749d94a2e61";

var queryStringTemplate = "..NestedRepetable[?(@.GUID == '{0}')]";
var query = root.SelectTokens(string.Format(queryStringTemplate, value));

foreach (var obj in query.ToList())
    obj.Remove();

如果您实际上并不关心对象是否嵌套在"NestedRepetable"中(此时您的问题尚不清楚),您可以这样做

If you don't actually care whether the objects are nested inside "NestedRepetable" (your question is unclear on this point) you can just do

var queryStringTemplate = "..[?(@.GUID == '{0}')]";

注意:

  • ..递归下降运算符.它会返回JToken层次结构并返回所有值.

  • .. is the recursive descent operator. It descends the JToken hierarchy returning all values.

NestedRepetable将具有所需名称的属性值匹配.

NestedRepetable matches values of properties with the required name.

[?(@.GUID == '{0}')]使用具有指定值的名为GUID的属性来匹配属于NestedRepetable数组的对象.

[?(@.GUID == '{0}')] matches objects belonging to the NestedRepetable array with a property named GUID with the specified value.

在删除与查询匹配的令牌时,有必要通过调用ToList()来实现查询,以避免您看到的Collection was modified异常.

When removing tokens that match the query, it is necessary to materialize the query by calling ToList() to avoid the Collection was modified exception you are seeing.

有关JSONPath语法的更多信息,请参见 JSONPath-JSON的XPath .

For more on JSONPath syntax see JSONPath - XPath for JSON.

.net小提琴示例工作此处用于复杂查询和

Sample working .Net fiddle here for the complex query and here for the simpler query.

这篇关于如何按值查找json令牌,然后删除令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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