@@ -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,157 +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
-
134
133
Building Queries Programmatically
135
134
---------------------------------
136
135
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.
136
+ For more dynamic or complex query building, use the fluent API provided
137
+ by the :class: `Symfony\\ Component\\ JsonPath\\ JsonPath ` class. This lets you
138
+ construct a query object step by step. The ``JsonPath `` object can then be passed
139
+ to the crawler's :method: `Symfony\\ Component\\ JsonPath\\ JsonCrawler::find ` method.
141
140
142
141
The main advantage of the programmatic builder is that it automatically handles
143
- the correct escaping of keys and values, preventing syntax errors::
142
+ escaping of keys and values, preventing syntax errors::
144
143
145
144
use Symfony\Component\JsonPath\JsonPath;
146
145
147
146
$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 )
147
+ ->key('store') // selects the 'store' key
148
+ ->key('book') // then the 'book' key
149
+ ->index(1); // then the second item (indexes start at 0 )
151
150
152
- // The created $path object is equivalent to the string '$["store"]["book"][1]'
151
+ // the created $path object is equivalent to the string '$["store"]["book"][1]'
153
152
$book = $crawler->find($path);
154
153
155
154
// $book contains the book object for "Sword of Honour"
156
155
157
- The :class: `Symfony\\ Component\\ JsonPath\\ JsonPath ` class provides several methods to build your query:
156
+ The :class: `Symfony\\ Component\\ JsonPath\\ JsonPath ` class provides several
157
+ methods to build your query:
158
158
159
159
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::key `
160
- Adds a key selector. The key name will be properly escaped::
160
+ Adds a key selector. The key name is properly escaped::
161
161
162
- // Creates the path '$["key\"with\"quotes"]'
163
- $path = (new JsonPath())->key('key"with"quotes');
162
+ // creates the path '$["key\"with\"quotes"]'
163
+ $path = (new JsonPath())->key('key"with"quotes');
164
164
165
165
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::deepScan `
166
- Adds the descendant operator ``.. `` to perform a recursive search from the
167
- current point in the path::
166
+ Adds the descendant operator ``.. `` to perform a recursive search from the
167
+ current point in the path::
168
168
169
- // Get all prices in the store: '$["store"]..["price"]'
170
- $path = (new JsonPath())->key('store')->deepScan()->key('price');
169
+ // get all prices in the store: '$["store"]..["price"]'
170
+ $path = (new JsonPath())->key('store')->deepScan()->key('price');
171
171
172
172
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::all `
173
- Adds the wildcard operator ``[*] `` to select all items in an array or object::
173
+ Adds the wildcard operator ``[*] `` to select all items in an array or object::
174
174
175
- // Creates the path '$["store"]["book"][*]'
175
+ // creates the path '$["store"]["book"][*]'
176
176
$path = (new JsonPath())->key('store')->key('book')->all();
177
177
178
178
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::index `
179
- Adds an array index selector.
179
+ Adds an array index selector. Index numbers start at `` 0 `` .
180
180
181
181
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::first ` / :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::last `
182
- Shortcuts for ``index(0) `` and ``index(-1) `` respectively::
182
+ Shortcuts for ``index(0) `` and ``index(-1) `` respectively::
183
183
184
- // Get the last book: '$["store"]["book"][-1]'
185
- $path = (new JsonPath())->key('store')->key('book')->last();
184
+ // get the last book: '$["store"]["book"][-1]'
185
+ $path = (new JsonPath())->key('store')->key('book')->last();
186
186
187
187
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::slice `
188
- Adds an array slice selector ``[start:end:step] ``::
188
+ Adds an array slice selector ``[start:end:step] ``::
189
189
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);
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
193
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);
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
197
198
198
* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::filter `
199
- Adds a filter expression. The expression string is the part that goes inside
200
- the ``?() `` syntax::
199
+ Adds a filter expression. The expression string is the part that goes inside
200
+ the ``?() `` syntax::
201
201
202
- // Get expensive books: '$["store"]["book"][?(@.price > 20)]'
203
- $path = (new JsonPath())
204
- ->key('store')
205
- ->key('book')
206
- ->filter('@.price > 20');
202
+ // get expensive books: '$["store"]["book"][?(@.price > 20)]'
203
+ $path = (new JsonPath())
204
+ ->key('store')
205
+ ->key('book')
206
+ ->filter('@.price > 20');
207
207
208
208
Advanced Querying
209
209
-----------------
210
210
211
211
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
212
+ filters, refer to the `Querying with Expressions `_ section above. All these
213
+ features are supported and can be combined with the programmatic builder when
214
214
appropriate (e.g., inside a ``filter() `` expression).
215
215
216
216
Error Handling
217
217
--------------
218
218
219
- The component will throw specific exceptions for invalid input or queries:
219
+ The component throws specific exceptions for invalid input or queries:
220
+
221
+ * :class: `Symfony\\ Component\\ JsonPath\\ Exception\\ InvalidArgumentException `:
222
+ Thrown if the input to the ``JsonCrawler `` constructor is not a valid JSON string;
223
+ * :class: `Symfony\\ Component\\ JsonPath\\ Exception\\ InvalidJsonStringInputException `:
224
+ Thrown during a ``find() `` call if the JSON string is malformed (e.g., syntax error);
225
+ * :class: `Symfony\\ Component\\ JsonPath\\ Exception\\ JsonCrawlerException `:
226
+ Thrown for errors within the JsonPath expression itself, such as using an unknown function
220
227
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::
228
+ Example of handling errors::
224
229
225
230
use Symfony\Component\JsonPath\Exception\InvalidJsonStringInputException;
226
231
use Symfony\Component\JsonPath\Exception\JsonCrawlerException;
227
232
228
233
try {
229
- // Example of malformed JSON
234
+ // the following line contains malformed JSON
230
235
$crawler = new JsonCrawler('{"store": }');
231
236
$crawler->find('$..*');
232
237
} catch (InvalidJsonStringInputException $e) {
233
238
// ... handle error
234
239
}
235
240
236
241
try {
237
- // Example of an invalid query
242
+ // the following line contains an invalid query
238
243
$crawler->find('$.store.book[?unknown_function(@.price)]');
239
244
} catch (JsonCrawlerException $e) {
240
245
// ... handle error
241
246
}
242
247
243
- .. _`RFC 9535 - JSONPath` : https://datatracker.ietf.org/doc/html/rfc9535
248
+ .. _`RFC 9535 – JSONPath` : https://datatracker.ietf.org/doc/html/rfc9535
0 commit comments