#javascript #json #xpath #jsonpath
#javascript #json #xpath #jsonpath
Вопрос:
У меня есть JSON с массивом фильмов, как в https://www.w3resource.com/JSON/JSONPath-with-JavaScript.php но с дополнительным массивом актеров и с неявной информацией о типе (база данных, фильмы).
Я создал этот JSFiddle: https://jsfiddle.net/prorep/7nhvb6sg/15 /
Я пытаюсь отфильтровать этот массив для всех фильмов, в которых участвует определенный актер. Когда я пытаюсь сделать что-то вроде этого:
jsonPath(json, "$.[actors[?(@.id==2)]]")
Я получаю массив с актером только дважды, но не полный фильм. Поэтому я думаю, что проблема, возможно, связана с определением корневого элемента, но что также не работает, так это
$.*[...], $.[*][...], $[*.[...]], ...
Что я пытаюсь получить в результате:
[{
"name": "30 Minutes or Less",
"genre": "adventure",
"director": "Ruben Fleischer",
"Facebook_like": 114,
"actors": [{
"id": 2,
"name": "Jesse Eisenberg"
}]
},
{
"name": "The Social Network",
"genre": "Biography",
"director": "David Fincher",
"Facebook_like": 0,
"actors": [{
"id": 2,
"name": "Jesse Eisenberg"
}]
}
]
Ответ №1:
Хороший вопрос. Вы используете эталонную реализацию JSONPath от Goessner (парня, который придумал JSONPath) в своем примере, а также живой тест на странице руководства (ссылка для скачивания на странице, похоже, ссылается на немного другую версию). Запрос, который вы придумали, на самом деле не поддерживается, и он работает только частично. Вычисляемый путь совпадает с рекурсивным спуском, сопоставляющим все id
s со значением 2: $..[?(@.id==2)]
, часть актеров игнорируется. Вы можете назвать это ошибкой, неподдерживаемым синтаксисом или неполной реализацией. Проблема в том, что JSONPath (пока) не стандартизирован, и разные реализации имеют разные функции и более или менее тонкие определения путей.
Хотя это не работает в эталонной (JS) реализации, мы все еще можем найти другие реализации, которые могут запрашивать данные по запросу.
В мире JavaScript мы могли бы использовать JSONPath-Plus (который, вероятно, является одной из самых многофункциональных реализаций на сегодняшний день), используя расширенный синтаксис для захвата родительского $..[?(@.id ==2)]^
элемента, используя ^
в конце и флаг синтаксического анализатора, чтобы получить этот родительский элемент родительского элемента, т.Е. свойство, имеющее массив actors
JSONPath({json: json,
path: "$..[?(@.id ==2)]^",
wrap: false,
resultType: 'parent'});
как показано ниже:
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script type="module">
import {JSONPath} from 'https://cdn.jsdelivr.net/npm/jsonpath-plus@4.0.0/dist/index-es.js';
const json = [{
"name": "The Change-Up",
"genre": "comedy",
"director": "David Dobkin",
"Facebook_like": 252,
"actors": [{
"id": 1,
"name": "Ryan Reynolds"
}]
},
{
"name": "Rise of the Planet of the Apes",
"genre": "SciFi",
"director": "Rupert Wyatt",
"Facebook_like": 472,
"actors": []
},
{
"name": "30 Minutes or Less",
"genre": "adventure",
"director": "Ruben Fleischer",
"Facebook_like": 114,
"actors": [{
"id": 2,
"name": "Jesse Eisenberg"
}]
},
{
"name": "Final Destination 5",
"genre": "Horror",
"director": "Steven Quale",
"Facebook_like": 241,
"actors": []
},
{
"name": "The Social Network",
"genre": "Biography",
"director": "David Fincher",
"Facebook_like": 0,
"actors": [{
"id": 2,
"name": "Jesse Eisenberg"
}]
}
];
console.log(JSONPath({
json: json,
path: "$..[?(@.id ==2)]^",
wrap: false,
resultType: 'parent'
}));
</script>
Другой очень надежной реализацией JSONPath, которая может запрашивать запрошенные элементы, является реализация Jayway для Java. Опять же, следующий семантически обоснованный путь (для меня) не работает со многими другими реализациями:
$.[?(@.actors[*].id ==[2])]
Вы можете попробовать запрос самостоятельно онлайн здесь и дополнительно изучить различия между другими реализациями.
Реальность такова, что вам нужно обратиться к документации вашей конкретной реализации, чтобы эффективно использовать JSONPath в вашем проекте.
Комментарии:
1. Вы правы в том, что я не знал, что существуют различия между несколькими доступными реализациями. Спасибо, что привели альтернативные примеры.