Alexandre Daubois
Contributed by Alexandre Daubois in #59655 and #60188

Symfony 7.3 adds several new components to the growing collection of Symfony packages and components. This article showcases JsonPath, a powerful new tool to query and extract data from JSON.

Take the following JSON snippet:

1
2
3
4
5
6
$json = <<<'JSON'
    {"store": {"book": [
        {"category": "reference", "author": "Nigel Rees", "title": "Sayings", "price": 8.95},
        {"category": "fiction", "author": "Evelyn Waugh", "title": "Sword", "price": 12.99}
    ]}}
    JSON;

Just like the DomCrawler component for traversing HTML/XML, you'll first need to create a crawler before querying JSON:

1
2
3
use Symfony\Component\JsonPath\JsonCrawler;

$crawler = new JsonCrawler($json);

From there, use the find() method to run queries:

1
2
3
// querying for a property of some item (e.g. to get the title of the first book)
$result = $crawler->find('$.store.book[0].title');
// outputs: ['Sayings']

The query syntax follows the RFC 9535 (JSONPath: Query Expressions for JSON), giving you access to powerful features:

1
2
3
4
5
6
7
8
9
// extract descendants from items (e.g. to get all authors)
$result = $crawler->find('$..author');
// outputs: ['Nigel Rees', 'Evelyn Waugh']

// filter contents using expressions
$result = $crawler->find('$.store.book[?(@.price < 10)]');
// you can use functions like length(), count(), match(), etc.
$result = $crawler->find('$.store.book[?length(@.author) > 11]');
$result = $crawler->find('$.store.book[?match(@.author, "[A-Z].*el.+")]');

Do you prefer building queries fluently? The JsonPath component also supports a programmatic, chainable API:

1
2
3
4
5
6
7
8
9
10
use Symfony\Component\JsonPath\JsonPath;

$path = new JsonPath();
$path = $path
    ->key('store')
        ->key('book')
            ->index(0)
                ->key('author');
$result = $crawler->find($path);
// outputs: ['Nigel Rees']
Published in #Living on the edge