У меня, например, такой Json, как в С#:
{
"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
, желаемый результат будет выглядеть так:
{
"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) в этом случае и значение в поле, которое должно быть удалено.
Я попытался сделать это так, как описано в этом вопросе, но они используют hardcoded путь json. Это не мое дело.
Я использовал следующий код:
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;
}
Но я получаю следующую ошибку:
Коллекция была изменена; операция перечисления не может выполняться "
Вероятно, потому что я пытаюсь удалить родительский элемент.
Вы пытаетесь найти и удалить объекты, которые соответствуют следующим критериям:
"NestedRepetable"
"GUID"
с определенным значением. Самый простой способ сделать это - использовать JToken.SelectTokens()
с запросом JSONPath:
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"
вложены ли объекты внутри "NestedRepetable"
(на данный момент ваш вопрос неясно), вы можете просто сделать
var queryStringTemplate = "..[?(@.GUID == '{0}')]";
Заметки:
..
является рекурсивным спускающим оператором. Он опускает иерархию JToken
возвращая все значения.
NestedRepetable
сопоставляет значения свойств с требуемым именем.
[?(@.GUID == '{0}')]
сопоставляет объекты, принадлежащие массиву NestedRepetable
с свойством с именем GUID
с указанным значением.
При удалении токенов, соответствующих запросу, необходимо выполнить запрос, вызвав ToList()
чтобы избежать Collection was modified
вы видели в Collection was modified
.
Подробнее о синтаксисе JSONPath см. JSONPath - XPath для JSON.
Пример работы.Net скрипку здесь для сложного запроса и здесь для более простого запроса.