问题
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"
}
]
}
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"
}
]
}
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.
I've used the following code :
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;
}
But I'm receiving the following error :
Collection was modified; enumeration operation may not execute"
Probably because I'm trying to remove the parent element.
回答1:
You are attempting to find and remove objects that match the following criteria:
- All objects contained by an array property named
"NestedRepetable"
- that have a property named
"GUID"
with a specific value.
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();
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}')]";
Notes:
..
is the recursive descent operator. It descends theJToken
hierarchy returning all values.NestedRepetable
matches values of properties with the required name.[?(@.GUID == '{0}')]
matches objects belonging to theNestedRepetable
array with a property namedGUID
with the specified value.When removing tokens that match the query, it is necessary to materialize the query by calling
ToList()
to avoid theCollection was modified
exception you are seeing.For more on JSONPath syntax see JSONPath - XPath for JSON.
Sample working .Net fiddle here for the complex query and here for the simpler query.
来源:https://stackoverflow.com/questions/52149657/how-to-find-json-token-by-value-and-then-delete-the-token