Skip to content

Commit f547cc7

Browse files
javiereguiluzOskarStark
authored andcommitted
[JsonPath] Minor fixes and tweaks
1 parent 974e9d1 commit f547cc7

File tree

1 file changed

+78
-73
lines changed

1 file changed

+78
-73
lines changed

components/json_path.rst

Lines changed: 78 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1719
Installation
1820
------------
@@ -29,8 +31,8 @@ Usage
2931
-----
3032

3133
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::
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

8183
Querying with Expressions
8284
-------------------------
@@ -87,157 +89,160 @@ to the :method:`Symfony\\Component\\JsonPath\\JsonCrawler::find` method.
8789
Accessing 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
9193
of 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

109113
Searching with the Descendant Operator
110114
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111115

112116
The descendant operator (``..``) recursively searches for a given key, allowing
113117
you 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

120124
Filtering 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-
134133
Building Queries Programmatically
135134
---------------------------------
136135

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.
141140

142141
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::
144143

145144
use Symfony\Component\JsonPath\JsonPath;
146145

147146
$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)
151150

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]'
153152
$book = $crawler->find($path);
154153

155154
// $book contains the book object for "Sword of Honour"
156155

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:
158158

159159
* :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::
161161

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');
164164

165165
* :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::
168168

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');
171171

172172
* :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::
174174

175-
// Creates the path '$["store"]["book"][*]'
175+
// creates the path '$["store"]["book"][*]'
176176
$path = (new JsonPath())->key('store')->key('book')->all();
177177

178178
* :method:`Symfony\\Component\\JsonPath\\JsonPath::index`
179-
Adds an array index selector.
179+
Adds an array index selector. Index numbers start at ``0``.
180180

181181
* :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::
183183

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();
186186

187187
* :method:`Symfony\\Component\\JsonPath\\JsonPath::slice`
188-
Adds an array slice selector ``[start:end:step]``::
188+
Adds an array slice selector ``[start:end:step]``::
189189

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);
193193

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);
197197

198198
* :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::
201201

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');
207207

208208
Advanced Querying
209209
-----------------
210210

211211
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
214214
appropriate (e.g., inside a ``filter()`` expression).
215215

216216
Error Handling
217217
--------------
218218

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
220227

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::
224229

225230
use Symfony\Component\JsonPath\Exception\InvalidJsonStringInputException;
226231
use Symfony\Component\JsonPath\Exception\JsonCrawlerException;
227232

228233
try {
229-
// Example of malformed JSON
234+
// the following line contains malformed JSON
230235
$crawler = new JsonCrawler('{"store": }');
231236
$crawler->find('$..*');
232237
} catch (InvalidJsonStringInputException $e) {
233238
// ... handle error
234239
}
235240

236241
try {
237-
// Example of an invalid query
242+
// the following line contains an invalid query
238243
$crawler->find('$.store.book[?unknown_function(@.price)]');
239244
} catch (JsonCrawlerException $e) {
240245
// ... handle error
241246
}
242247

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

Comments
 (0)