|
| 1 | +The JsonPath Component |
| 2 | +====================== |
| 3 | + |
| 4 | +.. versionadded:: 7.3 |
| 5 | + The JsonPath component was introduced in Symfony 7.3. |
| 6 | + |
| 7 | +The JsonPath component provides a powerful way to query and extract data from |
| 8 | +JSON structures. It implements the `RFC 9535 (JSONPath) <https://datatracker.ietf.org/doc/html/rfc9535>`_ |
| 9 | +standard, allowing you to navigate complex JSON data with ease. |
| 10 | + |
| 11 | +Think of it as :doc:`the DomCrawler component </components/dom_crawler>`, but for JSON. |
| 12 | + |
| 13 | +Installation |
| 14 | +------------ |
| 15 | + |
| 16 | +You can install the component in your project using Composer: |
| 17 | + |
| 18 | +.. code-block:: terminal |
| 19 | +
|
| 20 | + $ composer require symfony/json-path |
| 21 | +
|
| 22 | +.. include:: /components/require_autoload.rst.inc |
| 23 | + |
| 24 | +Basic Usage |
| 25 | +----------- |
| 26 | + |
| 27 | +To start querying a JSON document, you first need to create a :class:`Symfony\\Component\\JsonPath\\JsonCrawler` |
| 28 | +object from a JSON string: |
| 29 | + |
| 30 | +.. code-block:: php |
| 31 | +
|
| 32 | + use Symfony\Component\JsonPath\JsonCrawler; |
| 33 | +
|
| 34 | + $json = <<<'JSON' |
| 35 | + { |
| 36 | + "store": { |
| 37 | + "book": [ |
| 38 | + { |
| 39 | + "category": "reference", |
| 40 | + "author": "Nigel Rees", |
| 41 | + "title": "Sayings", |
| 42 | + "price": 8.95 |
| 43 | + }, |
| 44 | + { |
| 45 | + "category": "fiction", |
| 46 | + "author": "Evelyn Waugh", |
| 47 | + "title": "Sword", |
| 48 | + "price": 12.99 |
| 49 | + } |
| 50 | + ] |
| 51 | + } |
| 52 | + } |
| 53 | + JSON; |
| 54 | +
|
| 55 | + $crawler = new JsonCrawler($json); |
| 56 | +
|
| 57 | +Once you have the crawler instance, you can use its ``find()`` method to start |
| 58 | +querying the data. |
| 59 | + |
| 60 | +Querying with Expressions |
| 61 | +------------------------- |
| 62 | + |
| 63 | +The primary way to query the JSON is by passing a JSONPath expression string |
| 64 | +to the ``find()`` method. This method always returns an array of matching values. |
| 65 | + |
| 66 | +**Accessing a Specific Property** |
| 67 | + |
| 68 | +Use dot-notation for object keys and square brackets for array indices. The root |
| 69 | +of the document is represented by ``$``. |
| 70 | + |
| 71 | +.. code-block:: php |
| 72 | +
|
| 73 | + // Get the title of the first book in the store |
| 74 | + $titles = $crawler->find('$.store.book[0].title'); |
| 75 | +
|
| 76 | + // $titles is ['Sayings'] |
| 77 | +
|
| 78 | +**Searching with the Descendant Operator** |
| 79 | + |
| 80 | +The descendant operator (``..``) recursively searches for a given key, allowing |
| 81 | +you to find values without specifying the full path. |
| 82 | + |
| 83 | +.. code-block:: php |
| 84 | +
|
| 85 | + // Get all authors from anywhere in the document |
| 86 | + $authors = $crawler->find('$..author'); |
| 87 | +
|
| 88 | + // $authors is ['Nigel Rees', 'Evelyn Waugh'] |
| 89 | +
|
| 90 | +**Filtering Results** |
| 91 | + |
| 92 | +JSONPath includes a powerful filter syntax (``?(<expression>)``) to select items |
| 93 | +based on a condition. The current item within the filter is referenced by ``@``. |
| 94 | + |
| 95 | +.. code-block:: php |
| 96 | +
|
| 97 | + // Get all books with a price less than 10 |
| 98 | + $cheapBooks = $crawler->find('$.store.book[?(@.price < 10)]'); |
| 99 | +
|
| 100 | + /* |
| 101 | + $cheapBooks contains: |
| 102 | + [ |
| 103 | + [ |
| 104 | + "category" => "reference", |
| 105 | + "author" => "Nigel Rees", |
| 106 | + "title" => "Sayings", |
| 107 | + "price" => 8.95, |
| 108 | + ], |
| 109 | + ] |
| 110 | + */ |
| 111 | +
|
| 112 | +**Using Functions in Filters** |
| 113 | + |
| 114 | +The filter expressions also support a set of built-in functions, such as |
| 115 | +``length()``, ``count()``, and ``match()``. |
| 116 | + |
| 117 | +.. code-block:: php |
| 118 | +
|
| 119 | + // Get books where the author's name is longer than 11 characters |
| 120 | + $result = $crawler->find('$.store.book[?length(@.author) > 11]'); |
| 121 | +
|
| 122 | + // $result contains the book by "Evelyn Waugh" |
| 123 | +
|
| 124 | + // Get books where the author's name matches a regular expression |
| 125 | + $result = $crawler->find('$.store.book[?match(@.author, "[A-Z].*el.+")]'); |
| 126 | +
|
| 127 | + // $result contains the book by "Nigel Rees" |
| 128 | +
|
| 129 | +
|
| 130 | +Building Queries Programmatically |
| 131 | +------------------------------- |
| 132 | + |
| 133 | +For more dynamic or complex query building, you can use the fluent API provided |
| 134 | +by the :class:`Symfony\\Component\\JsonPath\\JsonPath` class. This allows you |
| 135 | +to construct a query object step-by-step: |
| 136 | + |
| 137 | +.. code-block:: php |
| 138 | +
|
| 139 | + use Symfony\Component\JsonPath\JsonPath; |
| 140 | +
|
| 141 | + $path = (new JsonPath()) |
| 142 | + ->key('store') |
| 143 | + ->key('book') |
| 144 | + ->index(0) |
| 145 | + ->key('author'); |
| 146 | +
|
| 147 | + // The created $path object is equivalent to the string '$.store.book[0].author' |
| 148 | +
|
| 149 | + $authors = $crawler->find($path); |
| 150 | +
|
| 151 | + // $authors is ['Nigel Rees'] |
| 152 | +
|
| 153 | +You can pass either the expression string or the ``JsonPath`` object to the |
| 154 | +``find()`` method. |
0 commit comments