@@ -6,13 +6,15 @@ The JsonPath Component
66 The JsonPath component was introduced in Symfony 7.3 as an
77 :doc: `experimental feature </contributing/code/experimental >`.
88
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.
1212
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.
1618
1719Installation
1820------------
2931-----
3032
3133To 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::
3436
3537 use Symfony\Component\JsonPath\JsonCrawler;
3638
@@ -75,8 +77,8 @@ object from a JSON string. For the following examples, we'll use this sample
7577
7678 $crawler = new JsonCrawler($json);
7779
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.
8082
8183Querying with Expressions
8284-------------------------
@@ -87,154 +89,160 @@ to the :method:`Symfony\\Component\\JsonPath\\JsonCrawler::find` method.
8789Accessing a Specific Property
8890~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8991
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
9193of the document is represented by ``$ ``::
9294
93- // Get the title of the first book in the store
95+ // get the title of the first book in the store
9496 $titles = $crawler->find('$.store.book[0].title');
9597
9698 // $titles is ['Sayings of the Century']
9799
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::
99103
100- // This is equivalent to the previous example and works with special keys
104+ // this is equivalent to the previous example
101105 $titles = $crawler->find('$["store"]["book"][0]["title"]');
102106
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"]') ;
105109
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' );
108112
109113Searching with the Descendant Operator
110114~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111115
112116The descendant operator (``.. ``) recursively searches for a given key, allowing
113117you to find values without specifying the full path::
114118
115- // Get all authors from anywhere in the document
119+ // get all authors from anywhere in the document
116120 $authors = $crawler->find('$..author');
117121
118122 // $authors is ['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'John Ronald Reuel Tolkien']
119123
120124Filtering Results
121125~~~~~~~~~~~~~~~~~
122126
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 ``@ ``::
125129
126- // Get all books with a price less than 10
130+ // get all books with a price less than 10
127131 $cheapBooks = $crawler->find('$.store.book[?(@.price < 10)]');
128132
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" */
133135
134136Building Queries Programmatically
135137---------------------------------
136138
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.
141143
142144The 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::
144146
145147 use Symfony\Component\JsonPath\JsonPath;
146148
147149 $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 )
151153
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]'
153155 $book = $crawler->find($path);
154156
155157 // $book contains the book object for "Sword of Honour"
156158
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:
158161
159162* :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::
161164
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');
164167
165168* :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::
168171
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');
171174
172175* :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::
174177
175- // Creates the path '$["store"]["book"][*]'
178+ // creates the path '$["store"]["book"][*]'
176179 $path = (new JsonPath())->key('store')->key('book')->all();
177180
178181* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::index `
179- Adds an array index selector.
182+ Adds an array index selector. Index numbers start at `` 0 `` .
180183
181184* :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::
183186
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();
186189
187190* :method: `Symfony\\ Component\\ JsonPath\\ JsonPath::slice `
188- Adds an array slice selector ``[start:end:step] ``::
191+ Adds an array slice selector ``[start:end:step] ``::
189192
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);
193196
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);
197200
198201* :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::
201204
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');
207210
208211Advanced Querying
209212-----------------
210213
211214For 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
214217appropriate (e.g., inside a ``filter() `` expression).
215218
216219Error Handling
217220--------------
218221
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
220230
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::
224232
225233 use Symfony\Component\JsonPath\Exception\InvalidJsonStringInputException;
226234 use Symfony\Component\JsonPath\Exception\JsonCrawlerException;
227235
228236 try {
229- // Example of malformed JSON
237+ // the following line contains malformed JSON
230238 $crawler = new JsonCrawler('{"store": }');
231239 $crawler->find('$..*');
232240 } catch (InvalidJsonStringInputException $e) {
233241 // ... handle error
234242 }
235243
236244 try {
237- // Example of an invalid query
245+ // the following line contains an invalid query
238246 $crawler->find('$.store.book[?unknown_function(@.price)]');
239247 } catch (JsonCrawlerException $e) {
240248 // ... handle error
0 commit comments