@@ -6,13 +6,15 @@ The JsonPath Component
6
6
The JsonPath component was introduced in Symfony 7.3 as an
7
7
:doc: `experimental feature </contributing/code/experimental >`.
8
8
9
- The JsonPath component provides a powerful way to query and extract data from
10
- JSON structures. It implements the `RFC 9535 - JSONPath `_
11
- standard, allowing you to navigate complex JSON data with ease .
9
+ The JsonPath component lets you query and extract data from JSON structures.
10
+ It implements the `RFC 9535 – JSONPath `_ standard, allowing you to navigate
11
+ complex JSON data.
12
12
13
- Just as the :doc: `DomCrawler component </components/dom_crawler >` allows you to navigate and query HTML/XML documents
14
- using XPath, the JsonPath component provides a similar experience to traverse and search JSON structures
15
- using JSONPath expressions. The component also offers an abstraction layer for data extraction.
13
+ Similar to the :doc: `DomCrawler component </components/dom_crawler >`, which lets
14
+ you navigate and query HTML or XML documents with XPath, the JsonPath component
15
+ offers the same convenience for traversing and searching JSON structures through
16
+ JSONPath expressions. The component also provides an abstraction layer for data
17
+ extraction.
16
18
17
19
Installation
18
20
------------
29
31
-----
30
32
31
33
To start querying a JSON document, first create a :class: `Symfony\\ Component\\ JsonPath\\ JsonCrawler `
32
- object from a JSON string. For the following examples, we'll use this sample
33
- "bookstore" JSON data::
34
+ object from a JSON string. The following examples use this sample "bookstore"
35
+ JSON data::
34
36
35
37
use Symfony\Component\JsonPath\JsonCrawler;
36
38
@@ -75,8 +77,8 @@ object from a JSON string. For the following examples, we'll use this sample
75
77
76
78
$crawler = new JsonCrawler($json);
77
79
78
- Once you have the crawler instance, use its :method: `Symfony\\ Component\\ JsonPath\\ JsonCrawler::find ` method to start querying
79
- the data. This method always returns an array of matching values.
80
+ Once you have the crawler instance, use its :method: `Symfony\\ Component\\ JsonPath\\ JsonCrawler::find `
81
+ method to start querying the data. This method returns an array of matching values.
80
82
81
83
Querying with Expressions
82
84
-------------------------
@@ -87,154 +89,160 @@ to the :method:`Symfony\\Component\\JsonPath\\JsonCrawler::find` method.
87
89
Accessing a Specific Property
88
90
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
89
91
90
- Use dot- notation for object keys and square brackets for array indices. The root
92
+ Use dot notation for object keys and square brackets for array indices. The root
91
93
of the document is represented by ``$ ``::
92
94
93
- // Get the title of the first book in the store
95
+ // get the title of the first book in the store
94
96
$titles = $crawler->find('$.store.book[0].title');
95
97
96
98
// $titles is ['Sayings of the Century']
97
99
98
- While dot-notation is common, JSONPath offers alternative syntaxes which can be more flexible. For instance, bracket notation (`['...'] `) is required if a key contains spaces or special characters::
100
+ Dot notation is the default, but JSONPath provides other syntaxes for cases where
101
+ it doesn't work. Use bracket notation (``['...'] ``) when a key contains spaces
102
+ or special characters::
99
103
100
- // This is equivalent to the previous example and works with special keys
104
+ // this is equivalent to the previous example
101
105
$titles = $crawler->find('$["store"]["book"][0]["title"]');
102
106
103
- // You can also build the query programmatically for more complex scenarios
104
- use Symfony\Component\JsonPath\JsonPath ;
107
+ // this expression requires brackets because some keys use dots or spaces
108
+ $titles = $crawler->find('$["store"]["book collection"][0]["title.original"]') ;
105
109
106
- $path = (new JsonPath())->key('store')->key('book')->first()->key('title');
107
- $titles = $crawler->find($path );
110
+ // you can combine both notations
111
+ $titles = $crawler->find('$["store"].book[0].title' );
108
112
109
113
Searching with the Descendant Operator
110
114
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111
115
112
116
The descendant operator (``.. ``) recursively searches for a given key, allowing
113
117
you to find values without specifying the full path::
114
118
115
- // Get all authors from anywhere in the document
119
+ // get all authors from anywhere in the document
116
120
$authors = $crawler->find('$..author');
117
121
118
122
// $authors is ['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'John Ronald Reuel Tolkien']
119
123
120
124
Filtering Results
121
125
~~~~~~~~~~~~~~~~~
122
126
123
- JSONPath includes a powerful filter syntax (``?(< expression> ) ``) to select items
124
- based on a condition. The current item within the filter is referenced by ``@ ``::
127
+ JSONPath includes a filter syntax (``?(expression) ``) to select items based on
128
+ a condition. The current item within the filter is referenced by ``@ ``::
125
129
126
- // Get all books with a price less than 10
130
+ // get all books with a price less than 10
127
131
$cheapBooks = $crawler->find('$.store.book[?(@.price < 10)]');
128
132
129
- /*
130
- $cheapBooks contains two book objects:
131
- the one by "Nigel Rees" and the one by "Herman Melville"
132
- */
133
+ /* $cheapBooks contains two book objects:
134
+ the one by "Nigel Rees" and the one by "Herman Melville" */
133
135
134
136
Building Queries Programmatically
135
137
---------------------------------
136
138
137
- For more dynamic or complex query building, you can use the fluent API provided
138
- by the :class: `Symfony\\ Component\\ JsonPath\\ JsonPath ` class. This allows you
139
- to construct a query object step-by- step. The ``JsonPath `` object can then be
140
- passed to the crawler's :method: `Symfony\\ Component\\ JsonPath\\ JsonCrawler::find ` method.
139
+ For more dynamic or complex query building, use the fluent API provided
140
+ by the :class: `Symfony\\ Component\\ JsonPath\\ JsonPath ` class. This lets you
141
+ construct a query object step by step. The ``JsonPath `` object can then be passed
142
+ to the crawler's :method: `Symfony\\ Component\\ JsonPath\\ JsonCrawler::find ` method.
141
143
142
144
The main advantage of the programmatic builder is that it automatically handles
143
- the correct escaping of keys and values, preventing syntax errors::
145
+ escaping of keys and values, preventing syntax errors::
144
146
145
147
use Symfony\Component\JsonPath\JsonPath;
146
148
147
149
$path = (new JsonPath())
148
- ->key('store') // Selects the 'store' key
149
- ->key('book') // Then the 'book' key
150
- ->index(1); // Then the item at index 1 (the second book )
150
+ ->key('store') // selects the 'store' key
151
+ ->key('book') // then the 'book' key
152
+ ->index(1); // then the second item (indexes start at 0 )
151
153
152
- // The created $path object is equivalent to the string '$["store"]["book"][1]'
154
+ // the created $path object is equivalent to the string '$["store"]["book"][1]'
153
155
$book = $crawler->find($path);
154
156
155
157
// $book contains the book object for "Sword of Honour"
156
158
157
- The :class: `Symfony\\ Component\\ JsonPath\\ JsonPath ` class provides several methods to build your query:
159
+ The :class: `Symfony\\ Component\\ JsonPath\\ JsonPath ` class provides several
160
+ methods to build your query:
158
161
159
162
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::key `
160
- Adds a key selector. The key name will be properly escaped::
163
+ Adds a key selector. The key name is properly escaped::
161
164
162
- // Creates the path '$["key\"with\"quotes"]'
163
- $path = (new JsonPath())->key('key"with"quotes');
165
+ // creates the path '$["key\"with\"quotes"]'
166
+ $path = (new JsonPath())->key('key"with"quotes');
164
167
165
168
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::deepScan `
166
- Adds the descendant operator ``.. `` to perform a recursive search from the
167
- current point in the path::
169
+ Adds the descendant operator ``.. `` to perform a recursive search from the
170
+ current point in the path::
168
171
169
- // Get all prices in the store: '$["store"]..["price"]'
170
- $path = (new JsonPath())->key('store')->deepScan()->key('price');
172
+ // get all prices in the store: '$["store"]..["price"]'
173
+ $path = (new JsonPath())->key('store')->deepScan()->key('price');
171
174
172
175
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::all `
173
- Adds the wildcard operator ``[*] `` to select all items in an array or object::
176
+ Adds the wildcard operator ``[*] `` to select all items in an array or object::
174
177
175
- // Creates the path '$["store"]["book"][*]'
178
+ // creates the path '$["store"]["book"][*]'
176
179
$path = (new JsonPath())->key('store')->key('book')->all();
177
180
178
181
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::index `
179
- Adds an array index selector.
182
+ Adds an array index selector. Index numbers start at `` 0 `` .
180
183
181
184
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::first ` / :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::last `
182
- Shortcuts for ``index(0) `` and ``index(-1) `` respectively::
185
+ Shortcuts for ``index(0) `` and ``index(-1) `` respectively::
183
186
184
- // Get the last book: '$["store"]["book"][-1]'
185
- $path = (new JsonPath())->key('store')->key('book')->last();
187
+ // get the last book: '$["store"]["book"][-1]'
188
+ $path = (new JsonPath())->key('store')->key('book')->last();
186
189
187
190
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::slice `
188
- Adds an array slice selector ``[start:end:step] ``::
191
+ Adds an array slice selector ``[start:end:step] ``::
189
192
190
- // Get books from index 1 up to (but not including) index 3
191
- // Creates the path '$["store"]["book"][1:3]'
192
- $path = (new JsonPath())->key('store')->key('book')->slice(1, 3);
193
+ // get books from index 1 up to (but not including) index 3
194
+ // creates the path '$["store"]["book"][1:3]'
195
+ $path = (new JsonPath())->key('store')->key('book')->slice(1, 3);
193
196
194
- // Get every second book from the first four books
195
- // Creates the path '$["store"]["book"][0:4:2]'
196
- $path = (new JsonPath())->key('store')->key('book')->slice(0, 4, 2);
197
+ // get every second book from the first four books
198
+ // creates the path '$["store"]["book"][0:4:2]'
199
+ $path = (new JsonPath())->key('store')->key('book')->slice(0, 4, 2);
197
200
198
201
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::filter `
199
- Adds a filter expression. The expression string is the part that goes inside
200
- the ``?() `` syntax::
202
+ Adds a filter expression. The expression string is the part that goes inside
203
+ the ``?() `` syntax::
201
204
202
- // Get expensive books: '$["store"]["book"][?(@.price > 20)]'
203
- $path = (new JsonPath())
204
- ->key('store')
205
- ->key('book')
206
- ->filter('@.price > 20');
205
+ // get expensive books: '$["store"]["book"][?(@.price > 20)]'
206
+ $path = (new JsonPath())
207
+ ->key('store')
208
+ ->key('book')
209
+ ->filter('@.price > 20');
207
210
208
211
Advanced Querying
209
212
-----------------
210
213
211
214
For a complete overview of advanced operators like wildcards and functions within
212
- filters, please refer to the `Querying with Expressions `_ section above. All these
213
- features are supported and can be combined with the programmatic builder where
215
+ filters, refer to the `Querying with Expressions `_ section above. All these
216
+ features are supported and can be combined with the programmatic builder when
214
217
appropriate (e.g., inside a ``filter() `` expression).
215
218
216
219
Error Handling
217
220
--------------
218
221
219
- The component will throw specific exceptions for invalid input or queries:
222
+ The component throws specific exceptions for invalid input or queries:
223
+
224
+ * :class: `Symfony\\ Component\\ JsonPath\\ Exception\\ InvalidArgumentException `:
225
+ Thrown if the input to the ``JsonCrawler `` constructor is not a valid JSON string;
226
+ * :class: `Symfony\\ Component\\ JsonPath\\ Exception\\ InvalidJsonStringInputException `:
227
+ Thrown during a ``find() `` call if the JSON string is malformed (e.g., syntax error);
228
+ * :class: `Symfony\\ Component\\ JsonPath\\ Exception\\ JsonCrawlerException `:
229
+ Thrown for errors within the JsonPath expression itself, such as using an unknown function
220
230
221
- * :class: `Symfony\\ Component\\ JsonPath\\ Exception\\ InvalidArgumentException `: Thrown if the input to the ``JsonCrawler `` constructor is not a valid JSON string.
222
- * :class: `Symfony\\ Component\\ JsonPath\\ Exception\\ InvalidJsonStringInputException `: Thrown during a ``find() `` call if the JSON string is malformed (e.g., syntax error).
223
- * :class: `Symfony\\ Component\\ JsonPath\\ Exception\\ JsonCrawlerException `: Thrown for errors within the JsonPath expression itself, such as using an unknown function::
231
+ Example of handling errors::
224
232
225
233
use Symfony\Component\JsonPath\Exception\InvalidJsonStringInputException;
226
234
use Symfony\Component\JsonPath\Exception\JsonCrawlerException;
227
235
228
236
try {
229
- // Example of malformed JSON
237
+ // the following line contains malformed JSON
230
238
$crawler = new JsonCrawler('{"store": }');
231
239
$crawler->find('$..*');
232
240
} catch (InvalidJsonStringInputException $e) {
233
241
// ... handle error
234
242
}
235
243
236
244
try {
237
- // Example of an invalid query
245
+ // the following line contains an invalid query
238
246
$crawler->find('$.store.book[?unknown_function(@.price)]');
239
247
} catch (JsonCrawlerException $e) {
240
248
// ... handle error
0 commit comments