#java #jsonpath
#java #jsonpath
Вопрос:
Ситуация
- У меня есть JSON
- Я пытаюсь захватить каждый элемент в массиве, который содержит некоторые конкретные вложенные объекты. Сложность заключается в том, что некоторые из этих объектов вложены на разных глубинах.
- Я использую JayWay JSONPathhttps://github.com/json-path/JsonPath , и мой код работает точно так же, как https://jsonpath.herokuapp.com
Это предназначено для использования на нашей платформе,https://dashdash.com — электронная таблица с интеграциями для известных веб-сервисов (и ваших частных API тоже).
Частный случай (тестируемый)
Рассмотрим следующий исходный JSON, я хочу возвращать только элементы массива, которые имеют вложенные объекты B, C и G. G находится на другой глубине, чем B и C.
Ниже вы можете увидеть исходный код и 2 варианта возврата.
исходный JSON
[
{
"A":"val1",
"B":"val2",
"C":"val3",
"D":{
"E":[
{
"F":"val4"
}
],
"G":[
{
"H":"val5",
"I":"val6",
"J":"val7"
}
]
}
},
{
"A":"val8",
"B":"val9",
"C":"val10",
"D":{
"E":[
{
"F":"val11"
}
],
"G":[
{
"H":"val12",
"I":"val13",
"J":"val14"
}
]
}
},
{
"A":"val15",
"B":"val16"
},
{
"A":"val8",
"B":"val9",
"C":"val10",
"D":{
"E":[
{
"F":"val11"
}
]
}
}
]
Ожидаемый возврат Вариант 1.
[
{
"B":"val2",
"C":"val3",
"G":[
{
"H":"val5",
"I":"val6",
"J":"val7"
}
]
},
{
"B":"val9",
"C":"val10",
"G":[
{
"H":"val12",
"I":"val13",
"J":"val14"
}
]
}
]
Ожидаемый возврат Вариант 2.
[
{
"B":"val2",
"C":"val3",
"D":{
"E":[
{
"F":"val4"
}
],
"G":[
{
"H":"val5",
"I":"val6",
"J":"val7"
}
]
}
},
{
"B":"val9",
"C":"val10",
"D":{
"E":[
{
"F":"val11"
}
],
"G":[
{
"H":"val12",
"I":"val13",
"J":"val14"
}
]
}
}
]
Где я нахожусь
- Я могу извлечь все элементы массива, имеющие B, C и D, с помощью запроса
$..['B','C','D']
Я пытался извлечь B, C и G, но все следующие запросы завершаются неудачей:
$..['B','C','G']
: возвращает значение null.$..['B','C',['D'].['G']]
: возвращает только объекты внутри G.
Опять же, я использую JayWay JSONPath https://github.com/json-path/JsonPath , и мой код работает точно так же, как https://jsonpath.herokuapp.com .
Заранее спасибо
Ответ №1:
Вы можете решить эту проблему, установив для JayWay конфигурацию DEFAULT_PATH_LEAF_TO_NULL (как описано в официальной документации:https://github.com/json-path/JsonPath ) и после этого примените оценку сравнения с нулевым значением:
вот так:
$.[?(@.A != null amp;amp; @.B != null amp;amp; @.D != null amp;amp; @.D.G != null)]
или это:
$.[?((@.A != null amp;amp; @.B != null) amp;amp; ((@.D != null amp;amp; @.D.G != null) || (@.G != null)))]
Для установки DEFAULT_PATH_LEAF_TO_NULL вам следует изменить конфигурацию по умолчанию:
Configuration conf = Configuration.defaultConfiguration();
Configuration conf2 = conf.addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);
Примечание: Если вы используете устаревшую версию jayway, оператор сравнения может работать некорректно, для получения дополнительной информации см.https://code.google.com/archive/p/json-path/issues/27
Я протестировал это решение, и оно отлично работало для меня:
Тест выполнен на https://jsonpath.herokuapp.com / со следующим вводом:
[
{
"A":"val1",
"B":"val2",
"C":"val3",
"D":{
"E":[
{
"F":"val4"
}
],
"G":[
{
"H":"val5",
"I":"val6",
"J":"val7"
}
]
}
},
{
"A":"val8",
"B":"val9",
"C":"val10",
"D":{
"E":[
{
"F":"val11"
}
],
"G":[
{
"H":"val12",
"I":"val13",
"J":"val14"
}
]
}
},
{
"A":"val15",
"B":"val16"
},
{
"A":"val8",
"B":"val9",
"C":"val10",
"D":{
"E":[
{
"F":"val11"
}
]
}
}
]
и результатом было:
[
{
"A" : "val1",
"B" : "val2",
"C" : "val3",
"D" : {
"E" : [
{
"F" : "val4"
}
],
"G" : [
{
"H" : "val5",
"I" : "val6",
"J" : "val7"
}
]
}
},
{
"A" : "val8",
"B" : "val9",
"C" : "val10",
"D" : {
"E" : [
{
"F" : "val11"
}
],
"G" : [
{
"H" : "val12",
"I" : "val13",
"J" : "val14"
}
]
}
}
]
Дайте мне знать, если вам понадобится дополнительная помощь в этом.
Комментарии:
1. Я обнаружил незначительную проблему: — Проблема активации
DEFAULT_PATH_LEAF_TO_NULL
заключается в том, что другие функции будут возвращать нули, даже если пути не существуют. Пример: В Json « [ { «foo»: «foo1», «bar»: «bar1» }, { «foo»: «foo2» } ] « запросы «$ [*].bar» и «$ ..bar» вернут « [ «bar1», null ] ` ` там, где я хотел « [ «bar1» ] « Есть запрос конфигурация, которая решила бы обе проблемы? — выполнить сопоставление для существующих путей в [B, C, D.G] (или [B, C, ..G]); и — не возвращать нули дляanything
иseek
запросов?2. на самом деле, @dromualdo, ваш запрос почти готов, но он не проверяет существование свойства, скорее, свойство НЕ равно null. Это другое. Например, в приведенном выше JSON, если вы создадите [0].D.B = null, JSONPath, который я ищу, вернет 2 объекта, [0] и [1] — оба имеют B, C и ..G, и он возвращает только [1], потому что [0].B.G существует, но [0].B.G =null.
Ответ №2:
Я пробовал несколько разных подходов, и я думаю, что более простое выражение делает свое дело:
$.*[?(@.B amp;amp; @.C amp;amp; @.D.G)]
Для этого не требуется никакой специальной конфигурации, отличной от конфигурации по умолчанию (согласно эксперименту, проведенному на https://jsonpath.herokuapp.com и выдает следующий результат:
[
{
"A" : "val1",
"B" : "val2",
"C" : "val3",
"D" : {
"E" : [
{
"F" : "val4"
}
],
"G" : [
{
"H" : "val5",
"I" : "val6",
"J" : "val7"
}
]
}
},
{
"A" : "val8",
"B" : "val9",
"C" : "val10",
"D" : {
"E" : [
{
"F" : "val11"
}
],
"G" : [
{
"H" : "val12",
"I" : "val13",
"J" : "val14"
}
]
}
}
]
Что вы думаете?
Комментарии:
1. идеально! это то, что я искал!