Фильтровать массив с помощью JSONPath в зависимости от информации подмассива

#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. Вы правы в том, что я не знал, что существуют различия между несколькими доступными реализациями. Спасибо, что привели альтернативные примеры.