PHPackages                             remorhaz/php-json-path - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. remorhaz/php-json-path

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

remorhaz/php-json-path
======================

JSONPath implementation in PHP

v0.8.1(2y ago)15164.6k↓53.1%6[5 issues](https://github.com/remorhaz/php-json-path/issues)[1 PRs](https://github.com/remorhaz/php-json-path/pulls)1MITPHPPHP ~8.1.0 || ~8.2.0 || ~8.3.0CI failing

Since Jul 23Pushed 2y ago3 watchersCompare

[ Source](https://github.com/remorhaz/php-json-path)[ Packagist](https://packagist.org/packages/remorhaz/php-json-path)[ Docs](https://github.com/remorhaz/php-json-path)[ RSS](/packages/remorhaz-php-json-path/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (10)Dependencies (5)Versions (25)Used By (1)

PHP JSONPath
============

[](#php-jsonpath)

[![Latest Stable Version](https://camo.githubusercontent.com/847411c7aefca92ee546623e589596f751a6b7b2d119b443ac5f618420bdd43a/68747470733a2f2f706f7365722e707567782e6f72672f72656d6f7268617a2f7068702d6a736f6e2d706174682f76657273696f6e)](https://packagist.org/packages/remorhaz/php-json-path)[![Build](https://github.com/remorhaz/php-json-path/actions/workflows/build.yml/badge.svg)](https://github.com/remorhaz/php-json-path/actions/workflows/build.yml)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/1645adabbb5ebb1faa9ed5783fc4e52c31635accfeb37b39ac63e3fbf3634561/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f72656d6f7268617a2f7068702d6a736f6e2d706174682f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/remorhaz/php-json-path/?branch=master)[![codecov](https://camo.githubusercontent.com/0acfad332735f470bd13528697b7ec6da4e43c0d5f2b6eba5c2e6fd94e741fd5/68747470733a2f2f636f6465636f762e696f2f67682f72656d6f7268617a2f7068702d6a736f6e2d706174682f6272616e63682f6d61737465722f67726170682f62616467652e737667)](https://codecov.io/gh/remorhaz/php-json-path)[![Mutation testing badge](https://camo.githubusercontent.com/fa210a37cba2faf72c640ef22a4c1af870ab717d8f3abff4773a80a954ab308a/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f7374796c653d666c61742675726c3d687474707325334125324625324662616467652d6170692e737472796b65722d6d757461746f722e696f2532466769746875622e636f6d25324672656d6f7268617a2532467068702d6a736f6e2d706174682532466d6173746572)](https://dashboard.stryker-mutator.io/reports/github.com/remorhaz/php-json-path/master)[![Total Downloads](https://camo.githubusercontent.com/9bb5cb29ada562298fd5858d8f341bc9d3f9c8b26ac74f65826aecb943734f11/68747470733a2f2f706f7365722e707567782e6f72672f72656d6f7268617a2f7068702d6a736f6e2d706174682f646f776e6c6f616473)](https://packagist.org/packages/remorhaz/php-json-path)[![License](https://camo.githubusercontent.com/b7f558a7b67ef70abf691c34acb616ae0b900b39f5ff1b1230e09fe4391599ac/68747470733a2f2f706f7365722e707567782e6f72672f72656d6f7268617a2f7068702d6a736f6e2d706174682f6c6963656e7365)](https://packagist.org/packages/remorhaz/php-json-path)

JSONPath is a simple query language for JSON documents, inspired by XPath for XML and originally designed by [Stefan Goessner](https://goessner.net/articles/JsonPath/).

Features
--------

[](#features)

- Accepts encoded JSON strings as well as decoded PHP data as input, supports both representations in output.
- Selects, deletes or replaces parts of JSON document using JSONPath queries.
- Recognizes definite/indefinite JSONPath queries without executing them.
- Transforms indefinite JSONPath query to set of definite queries for given JSON document.

Requirements
------------

[](#requirements)

- PHP 8
- [JSON extension](https://www.php.net/manual/en/book.json.php) (ext-json) - required by [remorhaz/php-json-data](https://github.com/remorhaz/php-json-data) that is used to access JSON documents.
- [Internationalization functions](https://www.php.net/manual/en/book.intl.php) (ext-intl)
- [Tokenizer extension](https://www.php.net/manual/en/book.tokenizer.php) (ext-tokenizer) - required by [nikic/php-parser](https://github.com/nikic/PHP-Parser) that is used for code generation.

Installation
------------

[](#installation)

You can use Composer to install this package:

```
composer require remorhaz/php-json-path

```

Usage
-----

[](#usage)

### Accessing JSON document

[](#accessing-json-document)

You can create accessible JSON document either from encoded JSON string or from decoded JSON data using corresponding *node value factory*:

```
use Remorhaz\JSON\Data\Value\EncodedJson;
use Remorhaz\JSON\Data\Value\DecodedJson;

// Creating document from JSON-encoded string:
$encodedValueFactory = EncodedJson\NodeValueFactory::create();
$encodedJson = '{"a":1}';
$document1 = $encodedValueFactory->createValue($encodedJson);

// Creating document from decoded JSON data:
$decodedValueFactory = DecodedJson\NodeValueFactory::create();
$decodedJson = (object) ['a' => 1];
$document2 = $decodedValueFactory->createValue($decodedJson);
```

### Creating query

[](#creating-query)

You should use *query factory* to create query from JSONPath expression:

```
use Remorhaz\JSON\Path\Query\QueryFactory;

$queryFactory = QueryFactory::create();

// Creating query that selects all 'a' properties from any document:
$query = $queryFactory->createQuery('$..a');
```

*Definite* query is the query that defines exactly one path in document. If query includes any filters, wildcards or deep children scan, it is considered *indefinite*.

*Addressable* query is the query that returns unprocessed part(s) of the document. If query returns an aggregate function result, it is considered *non-addressable*.

### Processing query

[](#processing-query)

You should use an instance of *query processor* to execute queries on given JSON documents:

```
use Remorhaz\JSON\Path\Processor\Processor;

$processor = Processor::create();
```

#### Selecting part of a JSON document

[](#selecting-part-of-a-json-document)

There are two ways to select part of JSON document using JSONPath query:

1. You can get all matching parts in array, using `::select()` method. This works with both *definite* and *indefinite* queries. You will get empty array if none of document parts matches your query.
2. You can get exactly one matching part, using `::selectOne()` method. Note that this works only with *definite* queries. You will get an exception if your query is indefinite.

```
use Remorhaz\JSON\Data\Value\EncodedJson;
use Remorhaz\JSON\Path\Processor\Processor;
use Remorhaz\JSON\Path\Query\QueryFactory;

$processor = Processor::create()
$queryFactory = QueryFactory::create();
$encodedValueFactory = EncodedJson\NodeValueFactory::create();

$document = $encodedValueFactory->createValue('{"a":{"a":1,"b":2}');

// Selecting all 'a' properties (indefinite query, values exist):
$query1 = $queryFactory->createQuery('$..a');
$result1 = $processor->select($query1, $document);
var_dump($result1->select()); // array: ['{"a":1,"b":2}', '1']

// Selecting single 'b' property nested in 'a' property (definite query, value exists):
$query2 = $queryFactory->createQuery('$.a.b');
$result2 = $processor->selectOne($query2, $document);
var_dump($result2->exists()); // boolean: true
var_dump($result2->decode()); // integer: 2

// Selecting single 'b' property (definite query, value doesn't exist):
$query3 = $queryFactory->createQuery('$.b');
$result3 = $processor->selectOne($query3, $document);
var_dump($result3->exists()); // boolean: false
var_dump($result3->decode()); // throws exception
```

Note that you can either encode result(s) of a selection to JSON string(s) or decode them to raw PHP data. Before accessing a result of `::selectOne()` you can check it's existence with `::exists()` method to avoid exception.

#### Deleting part of a JSON document

[](#deleting-part-of-a-json-document)

To delete part(s) of a JSON document use `::delete()` method. It works only with *addressable* queries. You will get an exception if your query is non-addressable. If none of document parts match the query you will get the document unchanged. Special case is deleting root of a document - in this case you will get non-existing result.

```
use Remorhaz\JSON\Data\Value\EncodedJson;
use Remorhaz\JSON\Path\Processor\Processor;
use Remorhaz\JSON\Path\Query\QueryFactory;

$processor = Processor::create()
$queryFactory = QueryFactory::create();
$encodedValueFactory = EncodedJson\NodeValueFactory::create();

$document = $encodedValueFactory->createValue('{"a":{"a":1,"b":2}');

// Deleting all 'b' properties (value exists):
$query1 = $queryFactory->createQuery('$..b');
$result1 = $processor->delete($query1, $document);
var_dump($result1->exists()); // boolean: true
var_dump($result1->encode()); // '{"a":{"a":1}}'

// Deleting all 'c' properties (value doesn't exist):
$query2 = $queryFactory->createQuery('$..c');
$result2 = $processor->delete($query2, $document);
var_dump($result1->exists()); // boolean: true
var_dump($result1->encode()); // '{"a":{"a":1,"b":2}}'

// Deleting root of the document:
$query3 = $queryFactory->createValue('$');
$result3 = $processor->delete($query3, $document);
var_dump($result3->exists()); // boolean: false
var_dump($result3->encode()); // throws exception
```

#### Replacing the part of a JSON document with another JSON document

[](#replacing-the-part-of-a-json-document-with-another-json-document)

To replace part(s) of a JSON document with another JSON document use `::replace()` method. It works only with *addressable* queries. You will get an exception if your query is non-addressable. If none of document parts match the query you will get the document unchanged. If the query matches nested parts of a document, you will also get an exception.

```
use Remorhaz\JSON\Data\Value\EncodedJson;
use Remorhaz\JSON\Path\Processor\Processor;
use Remorhaz\JSON\Path\Query\QueryFactory;

$processor = Processor::create()
$queryFactory = QueryFactory::create();
$encodedValueFactory = EncodedJson\NodeValueFactory::create();

$document1 = $encodedValueFactory->createValue('{"a":{"a":1,"b":2}');
$document2 = $encodedValueFactory->createValue('{"c":3}');

// Replacing 'a' property (value exists):
$query1 = $queryFactory->createQuery('$.a');
$result1 = $processor->replace($query1, $document1, $document2);
var_dump($result1->encode()); // string: '{"a":{"c":3}}'

// Replacing all 'c' properties (value doesn't exist)
$query2 = $queryFactory->createQuery('$..c');
$result2 = $processor->replace($query2, $document1, $document2);
var_dump($result2->encode()); // string: '{"a":{"a":1,"b":2}'

// Replacing all 'a' properties (values are nested):
$query3 = $queryFactory->createQuery('$..a');
$result3 = $processor->replace($query3, $document1, $document2); // throws exception
```

Grammar
-------

[](#grammar)

All JSONPath queries start with abstract `$` symbol that denotes outer level object. Internal structure can be matched with child operators and filters:

OperationDescription`$`Root object of the JSON document.`.a`Property `a` of current object (dot-notation).`..a`Properties `a` of current and all it's nested objects.`['a']`Property `a` of current object (bracket-notation).`['a', 'b']`Properties `a` and `b` of current object.`[1, 3]`Indexes `1` and `3` of current array.`[3:10:2]`Sequence of indexes from `3` to `10` with step `2`.`*`Wildcard that matches any property of current object / index of current array.`[?()]`Filters values by expression.`.length()`Aggregate function.### Child operators

[](#child-operators)

There are two notations for selecting structure children: *dot*-notation and *bracket*-notation.

Dot-notation allows to select either exactly one property or all children (using a wildcard). *Double-dot* notation walks through the JSON structure recursively.

ExampleDescription`$.a`Selects property `a` of a root object.`$.*`Selects all properties of a root objects or all elements of a root array.`$..a`Selects property `a` of all objects recursively.`$..*`Selects all properties/elements of all objects/arrays recursively.Bracket-notation allows to select a set of properties/elements:

ExampleDescription`$['a', 'b']`Selects properties `a` and `b` of a root object.`$[2, 3]`Selects elements `2` and `3` from a root array.`$[3:10:2]`Selects a sequence of elements from `3` up to `10` with step `2`. This equivalent query is `$[3, 5, 7, 9]`. The notation is same as in Python.`$[*]`Select all children. Same as `$.*`.### Aggregate functions

[](#aggregate-functions)

Aggregate functions can be appended to any path in query and it will return calculated value.

FunctionDescription`.min()`Returns minimal number from current array.`.max()`Returns maximal number from current array.`.length()`Returns amount of elements in current array.`.avg()`Returns average value from numbers in current array.`.stddev()`Returns standard deviation from numbers in current array.The set of aggregate functions and idea itself is taken from [Java implementation](https://github.com/json-path/JsonPath).

### Filter expressions

[](#filter-expressions)

When filter is being applied to nodeset, it leaves only those nodes for which the expression evaluates to true.

ExampleDescription`$..a[?(@.b)]`Selects all properties `a` that contain objects with property `b`.`$..a[?(@.b > 2)]`Selects all properties `a` that contain objects with property `b` that is number greater than `2`.`$..a[?(true)]`Boolean `true` is the only literal that evaluates to `true`; so this query is equivalent to `$..a`.`$..a[?(1)]`**Attention!** This evaluates to `false`, selecting nothing, because no automatic typecasting is performed.#### Filter context

[](#filter-context)

Expression `@` points to the value to which the filter was applied.

#### Operators

[](#operators)

*Comparison operators* can be used to compare value with another value or with a literal. Supported operators are: `==`, `!=`, `>`, `>=`, `
