Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[JsonPath] Add the component#59655

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
fabpot merged 1 commit intosymfony:7.3fromalexandre-daubois:json-crawler
Mar 28, 2025

Conversation

alexandre-daubois
Copy link
Member

@alexandre-dauboisalexandre-daubois commentedJan 30, 2025
edited
Loading

QA
Branch?7.3
Bug fix?no
New feature?yes
Deprecations?no
IssuesFix#57280
LicenseMIT

JsonPath component

Today I'm presenting the JsonPath component. Thanks to this component, it will be possible to query JSON strings using the JSON Path syntax, as described in the recent RFC 9535. This RFC was released in February 2024 and is published here:https://datatracker.ietf.org/doc/html/rfc9535.

Here's a preview of what's possible:

<?phprequire'vendor/autoload.php';useSymfony\Component\JsonPath\JsonPath;useSymfony\Component\JsonPath\JsonCrawler;$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;$crawler =newJsonCrawler($json);// Basic property access$result =$crawler->find('$.store.book[0].title');// Array slice$result =$crawler->find('$.store.book[0:2]');// Reverse array slice$result =$crawler->find('$.store.book[::-1]');// Filter expression$result =$crawler->find('$.store.book[?(@.price < 10)]');// Recursive descent$result =$crawler->find('$..author');// Call to "length()"$result =$crawler->find('$.store.book[?length(@.author) > 11]');// Call to "match()"$result =$crawler->find('$.store.book[?match(@.author, "[A-Z].*el.+")]');// use a builder to create your path$path =newJsonPath();$path =$path->key('book')    ->index(0)    ->key('author');$result =$crawler->find($path);

As stated in RFC 9535, this component embeds a few read-to-use functions:

  • length
  • count
  • value
  • search
  • match

Integration of JsonStreamer for performance

Thanks to the powerfulness of JsonStreamer's Splitter, we're able to guess which part of the JSON needs and doesn't need to be decoded. Querying a whole node means we can onlyjson_decode() the substring containing the node. The same goes when encountering array keys. We extract the relevant substring thanks to Splitter that provides an API for that. It brings support for JSON-as-resource evaluation.

We stop when we encounter an operation that implies filtering as we need to decode the whole node to filter children.

What about other packages?

A few alternatives exist, however they were not updated in the last few years. If they are up-to-date, they do not seem to be following RFC 9535, but rather a partial implementation ofhttps://goessner.net/articles/JsonPath/.

Why not include it in DomCrawler or PropertyAccess?

That was my first thought, however DomCrawler and JsonPath actually share absolutely no logic and their purpose is really different. As they have not much in common, that would be no ideal to tie them up.

PropertyAccess could be another possibility, here's where I explained why I think this would not be a correct fit:#59655 (comment).

Does it need external dependencies?

No! This component is written in vanilla PHP and doesn't require any third-party package to work.

How will it be leveraged in Symfony/PHP?

So many possibilities 😉 The first I can think of is leveraging this component in integration tests.

Indeed, this would allow to easily validate and write new assert methods when writing integration tests with Symfony. Validating JSON returned by an API thanks to this notation would be way easier (and more readable). In short, HttpClient, BrowserKit andWebTestCase could beneficiate from this (especiallyBrowserKitAssertionsTrait where asserts on Json could be added!).

Symfony would not be the only beneficiary: we can easily imagine that libraries like Behat (or PHPUnit, why not) could use this package to implement asserts on JSON.

Apart from testing frameworks, this package can also be used to quickly extract precise data from a JSON. So, possibilities here are also endless.

Possible evolution

  • Leverage ExpressionLanguage to evaluate filters and allow user to inject its own filter functions (custom functions are allowed per the RFC)
  • Improve the JsonPath builder
  • XPath may be converted to JSON Path fairly easily, this could be something to investigate on

OskarStark, mvhirsch, daFish, yceruto, norkunas, dmaicher, damienfern, Kocal, mykiwi, soyuka, and 23 more reacted with thumbs up emojiOskarStark, daFish, JulienRAVIA, dsentker, ging-dev, supun-io, and rvanlaak reacted with hooray emojiantonkomarev, JulienRAVIA, Spomky, emanuel-okroj, lyrixx, ging-dev, jseparovic1, rvanlaak, and makraz reacted with heart emojiOskarStark, yceruto, javiereguiluz, dsentker, PabloKowalczyk, sstok, Chris53897, ging-dev, smnandre, supun-io, and 3 more reacted with rocket emojiKocal, Spomky, ging-dev, and supun-io reacted with eyes emoji
@mvhirsch
Copy link
Contributor

Symfony would not be the only beneficiary: we can easily imagine that libraries like Behat (or PHPUnit, why not) could use this package to implement asserts on JSON.

Not to forgetzenstruck/browser which hasopt-in support for jmespath. Having native support for JSONPath might be awesome. WDYT@kbond?

OskarStark, alexandre-daubois, silasjoisten, kbond, rvanlaak, and pavelmlejnek reacted with thumbs up emoji

@alexandre-dauboisalexandre-dauboisforce-pushed thejson-crawler branch 2 times, most recently from19f1073 to5669a25CompareJanuary 30, 2025 14:01
@hantsy
Copy link

As stated in RFC 9535, this component embeds a few read-to-use functions:

Add the rawjsonPath function to evaluate the JsonPath expression directly.

Copy link
Member

@KocalKocal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Cool!

alexandre-daubois reacted with heart emoji
@kbond
Copy link
Member

Not to forget zenstruck/browser which has opt-in support for jmespath. Having native support for JSONPath might be awesome. WDYT@kbond?

Absolutely! That's the first thing I thought of.

mvhirsch and alexandre-daubois reacted with heart emoji

@dunglas
Copy link
Member

Why "JsonCrawler" and not "JsonPath"?

valtzu, mvhirsch, OskarStark, GromNaN, dmaicher, 1ed, wouterj, supun-io, and xfifix reacted with thumbs up emoji

@alexandre-daubois
Copy link
MemberAuthor

Why "JsonCrawler" and not "JsonPath"?

Had the same thought earlier today, happy to see I'm not the only one! Let's see if anybody's against this naming. Otherwise, let's call it JsonPath, makes more sense to me as well.

dunglas and dmaicher reacted with thumbs up emoji

Copy link
Member

@GromNaNGromNaN left a comment
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I also think that JsonPath would be more appropriate as this is a well-known name of the spec that is implemented.

But maybe it should be part of thePropertyAccess? component. Why restrict this rich syntax to JSON documents when you can browse a tree of PHP objects in the same way. It would give more power to the PropertyAccess component.

rvanlaak reacted with eyes emoji
@alexandre-daubois
Copy link
MemberAuthor

alexandre-daubois commentedFeb 1, 2025
edited
Loading

@GromNaN I think that's a good question. Here's why I'm not 100% sure that would be a fit.

Why restrict this rich syntax to JSON documents when you can browse a tree of PHP objects in the same way

Given the complexity of PropertyAccess (the logic to know if a property is writable/readable, get the value, read it, etc. is far from being trivial), I'm afraid it would bring a lot more complexity to JsonPath. The few times I fixed something in PropertyAccess was a whole challenge by itself just to understand all supported cases. JsonPath only deals with always-readable scalar values in arrays, which makes thingsway more simple.However, what would be possible is to create something like a converter in a second time, to convert a JsonPath to a PropertyPath. PropertyAccess could then have an opt-in possibility to be used together with JsonPath.

It would give more power to the PropertyAccess component

Definitely, but wouldn't it be too much power actually? PropertyAccess is, again, very complex and supportsa lot of cases. But let's put implementation complexity aside. In my opinion, it would be very confusing for developers to have, in the same component, two different syntaxes that look alike, but doesn't have the same possibilities at all. For newcomers, it could be really puzzling.

Finally, if external packages (like testing frameworks and the ones I mentioned in the description) would like to support JsonPath, I'm not sure we should force to install the whole PropertyAccess component with it.

But I still think that having an opt-in dependency to JsonPath in PropertyAccess, to convert from one syntax to another, is something that may be investigated!

@alexandre-dauboisalexandre-dauboisforce-pushed thejson-crawler branch 2 times, most recently from1d6f001 toce60d57CompareFebruary 1, 2025 14:36
@alexandre-dauboisalexandre-daubois changed the title[JsonCrawler] Add the component[JsonPath] Add the componentFeb 1, 2025
@alexandre-daubois
Copy link
MemberAuthor

Thank you@GromNaN and@stof for your review, I addressed all comments and renamed the component JsonPath.

@alexandre-daubois
Copy link
MemberAuthor

Updated with JsonStreamer, thank you!

OskarStark and rvanlaak reacted with rocket emoji

@alexandre-daubois
Copy link
MemberAuthor

Rebased on 7.3.

Status: Needs Review

@alexandre-dauboisalexandre-dauboisforce-pushed thejson-crawler branch 2 times, most recently from6dca608 to1c96e3eCompareMarch 28, 2025 09:49
Copy link
Member

@nicolas-grekasnicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thinking loud about the scope and the name of the component: would it be the place to support navigating hypermedia APIs?

rvanlaak reacted with eyes emoji
@alexandre-daubois
Copy link
MemberAuthor

It deserves further investigation about the scope indeed, but we could imagine aJsonNavigator component (or something like that) that combines both JSON path manipulation and hypermedia JSON+LD APIs navigation. At first glance, it seems reasonable to me to have both under one component as JsonPath actually "navigates" through JSON trees.

GromNaN reacted with thumbs up emoji

@fabpot
Copy link
Member

Thank you@alexandre-daubois.

@fabpotfabpot merged commit38e0df1 intosymfony:7.3Mar 28, 2025
10 of 11 checks passed
fabpot added a commit that referenced this pull requestMar 28, 2025
…(alexandre-daubois)This PR was merged into the 7.3 branch.Discussion----------[JsonPath] Fix error message when evaluating a resource| Q             | A| ------------- | ---| Branch?       | 7.3| Bug fix?      | no| New feature?  | no| Deprecations? | no| Issues        | -| License       | MITAfter#59655 (comment)Commits-------e5cc3d4 [JsonPath] Fix error message when evaluating a resource
@fabpotfabpot mentioned this pull requestMay 2, 2025
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@GromNaNGromNaNGromNaN left review comments

@stofstofstof left review comments

@OskarStarkOskarStarkOskarStark left review comments

@xabbuhxabbuhxabbuh left review comments

@ycerutoycerutoyceruto left review comments

@KocalKocalKocal left review comments

@mtarldmtarldmtarld left review comments

@chalasrchalasrchalasr requested changes

@fabpotfabpotfabpot approved these changes

@nicolas-grekasnicolas-grekasnicolas-grekas approved these changes

Assignees
No one assigned
Projects
None yet
Milestone
7.3
Development

Successfully merging this pull request may close these issues.

Improve JSON assertion in Symfony Test
16 participants
@alexandre-daubois@mvhirsch@hantsy@kbond@dunglas@GromNaN@mtarld@fabpot@nicolas-grekas@stof@OskarStark@xabbuh@yceruto@Kocal@chalasr@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp