You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Rebuilt the test suite from scratch: removed bulky baseline fixtures and added compact unit/integration coverage for every filter (index, union, query, recursive, slice), lexer edge cases, and JSONPath core helpers. Runs reflection-free and deprecation-free.
- Achieved and enforced 100% code coverage across AccessHelper, all filters, lexer, tokens, and JSONPath core while keeping phpstan and coding standards clean.
- Added a lightweight manual query runner with curated examples to exercise selectors quickly without external datasets.
- Major compatibility push toward the unofficial JSONPath standard: unions support slices/queries/wildcards, trailing commas parse correctly, negative indexes and bracket-escaped keys (quotes, brackets, wildcards, special chars) are honored, filters compare path-to-path and root references, equality/deep-equality/regex/in/nin semantics align with expectations, and null existence/value handling follows RFC behavior.
- New feature highlights from this cycle:
- Multi-key unions with and without quotes: `$[name,year]` and `$["name","year"]`.
- Robust bracket notation for special/escaped keys, including `']'`, `'*'`, `$`, backslashes, and mixed punctuation.
- Trailing comma support in unions/slices (e.g. `$..books[0,1,2,]`).
- Negative index handling aligned with spec (short arrays return empty; -1 works where valid).
- Filter improvements: path-to-path/root comparisons, deep equality across scalars/objects/arrays/null/empties, regex matching, `in`/`nin`/`!in`, tautological expressions, and `?@` existence behavior per RFC.
- Unions combining slices/queries/wildcards now return complete results (e.g. `$[1:3,4]`, `$[*,1]`).
This fixes#72, fixes#61, fixes#60, fixes#59, fixes#58, fixes#51, fixes#44, fixes#41, fixes#40, fixes#39, fixes#38, fixes#37, fixes#36, fixes#35, fixes#34, fixes#33, fixes#32, fixes#31, fixes#30, fixes#29, fixes#9, closes#3
Signed-off-by: Sascha Greuel <github@1-2.dev>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+30-17Lines changed: 30 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,22 +1,35 @@
1
1
# Changelog
2
2
3
-
### 0.11.0
4
-
🔻 Breaking changes ahead:
5
-
6
-
- Dropped support for PHP < 8.5
7
-
-`JSONPathToken` now uses a `TokenType` enum and the constructor signature changed accordingly.
8
-
-`JSONPath` options flag is now an `int` bitmask (was `bool`), requiring callers to pass integer flags.
9
-
-`SliceFilter` returns an empty result for non-positive step values (previously iterated indefinitely).
10
-
-`QueryResultFilter` now throws a `JSONPathException` for unsupported operators instead of silently proceeding.
11
-
- Access helper behavior is stricter: `arrayValues` throws on invalid types; ArrayAccess lookups check `offsetExists` before reading; traversables and objects are handled distinctly.
12
-
- Adopted PHP 8.5 features: `TokenType` enum, readonly value object for tokens, typed flags/options, and `#[\Override]` usage.
13
-
- CI now runs on PHP 8.5 with required extensions; code style workflow updated accordingly.
14
-
- Added coverage for AccessHelper edge cases (magic getters, ArrayAccess, traversables, negative indexes), QueryResultFilter arithmetic branches, and SliceFilter negative/null bounds.
15
-
- Fixed empty-expression handling in lexer and improved safety in AccessHelper traversable lookups.
16
-
- Added PHPStan static analysis to the toolchain and addressed its findings.
17
-
18
-
### 0.10.1
19
-
- Fixed ignore whitespace after comparison value in filter expression
3
+
### 1.0.0
4
+
- Rebuilt the test suite from scratch: removed bulky baseline fixtures and added compact unit/integration coverage for every filter (index, union, query, recursive, slice), lexer edge cases, and JSONPath core helpers. Runs reflection-free and deprecation-free.
5
+
- Achieved and enforced 100% code coverage across AccessHelper, all filters, lexer, tokens, and JSONPath core while keeping phpstan and coding standards clean.
6
+
- Added a lightweight manual query runner with curated examples to exercise selectors quickly without external datasets.
7
+
- Major compatibility push toward the unofficial JSONPath standard: unions support slices/queries/wildcards, trailing commas parse correctly, negative indexes and bracket-escaped keys (quotes, brackets, wildcards, special chars) are honored, filters compare path-to-path and root references, equality/deep-equality/regex/in/nin semantics align with expectations, and null existence/value handling follows RFC behavior.
8
+
- New feature highlights from this cycle:
9
+
- Multi-key unions with and without quotes: `$[name,year]` and `$["name","year"]`.
10
+
- Robust bracket notation for special/escaped keys, including `']'`, `'*'`, `$`, backslashes, and mixed punctuation.
11
+
- Trailing comma support in unions/slices (e.g. `$..books[0,1,2,]`).
12
+
- Negative index handling aligned with spec (short arrays return empty; -1 works where valid).
13
+
- Filter improvements: path-to-path/root comparisons, deep equality across scalars/objects/arrays/null/empties, regex matching, `in`/`nin`/`!in`, tautological expressions, and `?@` existence behavior per RFC.
-`JSONPathToken` now uses a `TokenType` enum and the constructor signature changed accordingly.
21
+
-`JSONPath` options flag is now an `int` bitmask (was `bool`), requiring callers to pass integer flags.
22
+
-`SliceFilter` returns an empty result for non-positive step values (previously iterated indefinitely).
23
+
-`QueryResultFilter` now throws a `JSONPathException` for unsupported operators instead of silently proceeding.
24
+
- Access helper behavior is stricter: `arrayValues` throws on invalid types; ArrayAccess lookups check `offsetExists` before reading; traversables and objects are handled distinctly.
25
+
- Adopted PHP 8.5 features: `TokenType` enum, readonly value object for tokens, typed flags/options, and `#[\Override]` usage.
26
+
- CI now runs on PHP 8.5 with required extensions; code style workflow updated accordingly.
27
+
- Added coverage for AccessHelper edge cases (magic getters, ArrayAccess, traversables, negative indexes), QueryResultFilter arithmetic branches, and SliceFilter negative/null bounds.
28
+
- Fixed empty-expression handling in lexer and improved safety in AccessHelper traversable lookups.
29
+
- Added PHPStan static analysis to the toolchain and addressed its findings.
30
+
31
+
### 0.10.1
32
+
- Fixed ignore whitespace after comparison value in filter expression
20
33
21
34
### 0.10.0
22
35
- Fixed query/selector Filter Expression With Current Object
This is a [JSONPath](http://goessner.net/articles/JsonPath/) implementation for PHP based on Stefan Goessner's JSONPath script.
7
+
This is a [JSONPath](http://goessner.net/articles/JsonPath/) implementation for PHP that targets the de facto comparison suite/RFC semantics while keeping the API small, cached, and `eval`-free.
8
8
9
-
JSONPath is an XPath-like expression language for filtering, flattening and extracting data.
9
+
## Highlights
10
10
11
-
This project aims to be a clean and simple implementation with the following goals:
12
-
13
-
- Object-oriented code (should be easier to manage or extend in future)
14
-
- Expressions are parsed into tokens using code inspired by the Doctrine Lexer. The tokens are cached internally to avoid re-parsing the expressions.
15
-
- There is no `eval()` in use
16
-
- Any combination of objects/arrays/ArrayAccess-objects can be used as the data input which is great if you're de-serializing JSON in to objects or if you want to process your own data structures.
11
+
- PHP 8.5+ only, with enums/readonly tokens and no `eval`.
12
+
- Works with arrays, objects, and `ArrayAccess`/traversables in any combination.
13
+
- Unions cover slices/queries/wildcards/multi-key strings (quoted or unquoted); negative indexes and escaped bracket notation are supported.
14
+
- Filters support path-to-path/root comparisons, regex, `in`/`nin`/`!in`, deep equality, and RFC-style null existence/value handling.
15
+
- Tokenized parsing with internal caching; lightweight manual runner to try bundled examples quickly.
17
16
18
17
## Installation
19
18
20
19
Requires PHP 8.5 or newer.
21
20
22
21
```bash
23
-
composer require softcreatr/jsonpath:"^0.11"
22
+
composer require softcreatr/jsonpath:"^1.0"
24
23
```
25
24
26
25
## Development
27
26
28
-
Static analysis is done with PHPStan.
27
+
Useful commands:
29
28
30
29
```bash
31
-
composer require --dev phpstan/phpstan
32
-
./vendor/bin/phpstan analyse --no-progress
30
+
composer exec phpunit
31
+
composer phpstan
32
+
composer cs
33
33
```
34
34
35
35
## JSONPath Examples
@@ -43,6 +43,7 @@ JSONPath | Result
43
43
`$..books[(@.length-1)]` | the last book in order.
44
44
`$..books[-1:]` | the last book in order.
45
45
`$..books[0,1]` | the first two books
46
+
`$..books[title,year]` | multiple keys in a union
46
47
`$..books[:2]` | the first two books
47
48
`$..books[::2]` | every second book starting from first one
48
49
`$..books[1:6:3]` | every third book starting from 1 till 6
@@ -64,8 +65,8 @@ Symbol | Description
64
65
`*` | Wildcard. All child elements regardless their index.
65
66
`[,]` | Array indices as a set
66
67
`[start:end:step]` | Array slice operator borrowed from ES4/Python.
67
-
`?()` | Filters a result set by a script expression
68
-
`()` | Uses the result of a script expression as the index
68
+
`?()` | Filters a result set by a comparison expression
69
+
`()` | Uses the result of a comparison expression as the index
69
70
70
71
## PHP Usage
71
72
@@ -116,8 +117,6 @@ stdClass Object
116
117
*/
117
118
```
118
119
119
-
More examples can be found in the [Wiki](https://github.com/SoftCreatR/JSONPath/wiki/Queries)
120
-
121
120
### Magic method access
122
121
123
122
The options flag `JSONPath::ALLOW_MAGIC` will instruct JSONPath when retrieving a value to first check if an object
@@ -127,40 +126,47 @@ not very predictable as:
127
126
- wildcard and recursive features will only look at public properties and can't smell which properties are magically accessible
128
127
- there is no `property_exists` check for magic methods so an object with a magic `__get()` will always return `true` when checking
129
128
if the property exists
130
-
- any errors thrown or unpredictable behaviour caused by fetching via `__get()` is your own problem to deal with
129
+
- any errors thrown or unpredictable behavior caused by fetching via `__get()` is your own problem to deal with
131
130
132
131
```php
132
+
<?php
133
+
133
134
use Flow\JSONPath\JSONPath;
134
135
135
136
$myObject = (new Foo())->get('bar');
136
137
$jsonPath = new JSONPath($myObject, JSONPath::ALLOW_MAGIC);
137
138
```
138
139
139
-
For more examples, check the JSONPathTest.php tests file.
140
-
141
140
## Script expressions
142
141
143
-
Script expressions are not supported as the original author intended because:
142
+
Script execution is intentionally **not** supported:
144
143
145
-
- This would only be achievable through `eval` (boo).
146
-
- Using the script engine from different languages defeats the purpose of having a single expression evaluate the same way in different
147
-
languages which seems like a bit of a flaw if you're creating an abstract expression syntax.
144
+
- It would require `eval`, which we avoid.
145
+
- Behavior would diverge across languages and defeat having a portable expression syntax.
148
146
149
-
So here are the types of query expressions that are supported:
147
+
Supported filter/query patterns (200+ cases covered in the comparison suite):
150
148
151
-
[?(@._KEY_ _OPERATOR_ _VALUE_)] // <, >, <=, >=, !=, ==, =~, in and nin
152
-
e.g.
153
-
[?(@.title == "A string")] //
154
-
[?(@.title = "A string")]
155
-
// A single equals is not an assignment but the SQL-style of '=='
156
-
[?(@.title =~ /^a(nother)? string$/i)]
157
-
[?(@.title in ["A string", "Another string"])]
158
-
[?(@.title nin ["A string", "Another string"])]
159
-
160
-
## Known issues
161
-
162
-
- This project has not implemented multiple string indexes e.g. `$[name,year]` or `$["name","year"]`. I have no ETA on that feature, and it would require some re-writing of the parser that uses a very basic regex implementation.
[?(@['weird-key']=="ok")] // bracket-escaped keys and negative indexes
166
+
```
163
167
168
+
A full list of (un)supported filter/query patterns can be found in the [JSONPath Comparison Cheatsheet](https://cburgmer.github.io/json-path-comparison/).
169
+
164
170
## Similar projects
165
171
166
172
[FlowCommunications/JSONPath](https://github.com/FlowCommunications/JSONPath) is the predecessor of this library by Stephen Frank
0 commit comments