PHP Classes

File: tests/JSONPathTest.php

Recommend this page to a friend!
  Classes of Sascha Greuel   PHP JSON Path   tests/JSONPathTest.php   Download  
File: tests/JSONPathTest.php
Role: Class source
Content type: text/plain
Description: Class source
Class: PHP JSON Path
Query values from data structures like XPATH
Author: By
Last change:
Date: 3 years ago
Size: 22,693 bytes
 

Contents

Class file image Download
<?php /** * JSONPath implementation for PHP. * * @license https://github.com/SoftCreatR/JSONPath/blob/main/LICENSE MIT License */ declare(strict_types=1); namespace Flow\JSONPath\Test; use Flow\JSONPath\{JSONPath, JSONPathException}; use Flow\JSONPath\Test\Traits\TestDataTrait; use PHPUnit\Framework\TestCase; use function is_object; use function json_decode; use function json_encode; class JSONPathTest extends TestCase { use TestDataTrait; /** * $.store.books[0].title * * @throws JSONPathException */ public function testChildOperators(): void { $result = (new JSONPath($this->getData('example'))) ->find('$.store.books[0].title'); self::assertEquals('Sayings of the Century', $result[0]); } /** * @throws JSONPathException */ public function testIndexesObject(): void { $result = (new JSONPath($this->getData('indexed-object'))) ->find('$.store.books[3].title'); self::assertEquals('Sword of Honour', $result[0]); } /** * $['store']['books'][0]['title'] * * @throws JSONPathException */ public function testChildOperatorsAlt(): void { $result = (new JSONPath($this->getData('example'))) ->find("$['store']['books'][0]['title']"); self::assertEquals('Sayings of the Century', $result[0]); } /** * $.array[start:end:step] * * @throws JSONPathException */ public function testFilterSliceA(): void { // Copy all items... similar to a wildcard $result = (new JSONPath($this->getData('example'))) ->find("$['store']['books'][:].title"); self::assertEquals( ['Sayings of the Century', 'Sword of Honour', 'Moby Dick', 'The Lord of the Rings'], $result->getData() ); } /** * Positive end indexes * $[0:2] * * @throws JSONPathException */ public function testFilterSlicePositiveEndIndexes(): void { $jsonPath = (new JSONPath(['first', 'second', 'third', 'fourth', 'fifth'])); $result = $jsonPath ->find('$[0:0]'); self::assertEquals([], $result->getData()); $result = $jsonPath ->find('$[0:1]'); self::assertEquals(['first'], $result->getData()); $result = $jsonPath ->find('$[0:2]'); self::assertEquals(['first', 'second'], $result->getData()); $result = $jsonPath ->find('$[:2]'); self::assertEquals(['first', 'second'], $result->getData()); $result = $jsonPath ->find('$[1:2]'); self::assertEquals(['second'], $result->getData()); $result = $jsonPath ->find('$[0:3:1]'); self::assertEquals(['first', 'second', 'third'], $result->getData()); $result = $jsonPath ->find('$[0:3:0]'); self::assertEquals(['first', 'second', 'third'], $result->getData()); } /** * @throws JSONPathException */ public function testFilterSliceNegativeStartIndexes(): void { $result = (new JSONPath(['first', 'second', 'third', 'fourth', 'fifth'])) ->find('$[-2:]'); self::assertEquals(['fourth', 'fifth'], $result->getData()); $result = (new JSONPath(['first', 'second', 'third', 'fourth', 'fifth'])) ->find('$[-1:]'); self::assertEquals(['fifth'], $result->getData()); $result = (new JSONPath(['first', 'second', 'third'])) ->find('$[-4:]'); self::assertEquals(['first', 'second', 'third'], $result->getData()); } /** * Negative end indexes * $[:-2] * * @throws JSONPathException */ public function testFilterSliceNegativeEndIndexes(): void { $jsonPath = (new JSONPath(['first', 'second', 'third', 'fourth', 'fifth'])); $result = $jsonPath ->find('$[:-2]'); self::assertEquals(['first', 'second', 'third'], $result->getData()); $result = $jsonPath ->find('$[0:-2]'); self::assertEquals(['first', 'second', 'third'], $result->getData()); } /** * Negative end indexes * $[:-2] * * @throws JSONPathException */ public function testFilterSliceNegativeStartAndEndIndexes(): void { $jsonPath = (new JSONPath(['first', 'second', 'third', 'fourth', 'fifth'])); $result = $jsonPath ->find('$[-2:-1]'); self::assertEquals(['fourth'], $result->getData()); $result = $jsonPath ->find('$[-4:-2]'); self::assertEquals(['second', 'third'], $result->getData()); } /** * Negative end indexes * $[:-2] * * @throws JSONPathException */ public function testFilterSliceNegativeStartAndPositiveEnd(): void { $result = (new JSONPath(['first', 'second', 'third', 'fourth', 'fifth'])) ->find('$[-2:2]'); self::assertEquals([], $result->getData()); } /** * @throws JSONPathException */ public function testFilterSliceStepBy2(): void { $result = (new JSONPath(['first', 'second', 'third', 'fourth', 'fifth'])) ->find('$[0:4:2]'); self::assertEquals(['first', 'third'], $result->getData()); } /** * The Last item * $[-1] * * @throws JSONPathException */ public function testFilterLastIndex(): void { $result = (new JSONPath(['first', 'second', 'third', 'fourth', 'fifth'])) ->find('$[-1]'); self::assertEquals(['fifth'], $result->getData()); } /** * Array index slice only end * $[:2] * * @throws JSONPathException */ public function testFilterSliceG(): void { // Fetch up to the second index $result = (new JSONPath(['first', 'second', 'third', 'fourth', 'fifth'])) ->find('$[:2]'); self::assertEquals(['first', 'second'], $result->getData()); } /** * $.store.books[(@.length-1)].title * * This notation is only partially implemented eg. hacked in * * @throws JSONPathException */ public function testChildQuery(): void { $result = (new JSONPath($this->getData('example'))) ->find('$.store.books[(@.length-1)].title'); self::assertEquals(['The Lord of the Rings'], $result->getData()); } /** * $.store.books[?(@.price < 10)].title * Filter books that have a price less than 10 * * @throws JSONPathException */ public function testQueryMatchLessThan(): void { $result = (new JSONPath($this->getData('example'))) ->find('$.store.books[?(@.price < 10)].title'); self::assertEquals(['Sayings of the Century', 'Moby Dick'], $result->getData()); } /** * $.store.books[?(@.price > 10)].title * Filter books that have a price more than 10 * * @throws JSONPathException */ public function testQueryMatchMoreThan(): void { $result = (new JSONPath($this->getData('example'))) ->find('$.store.books[?(@.price > 10)].title'); self::assertEquals(['Sword of Honour', 'The Lord of the Rings'], $result->getData()); } /** * $.store.books[?(@.price <= 12.99)].title * Filter books that have a price less or equal to 12.99 * * @throws JSONPathException */ public function testQueryMatchLessOrEqual(): void { $result = (new JSONPath($this->getData('example'))) ->find('$.store.books[?(@.price <= 12.99)].title'); self::assertEquals(['Sayings of the Century', 'Sword of Honour', 'Moby Dick'], $result->getData()); } /** * $.store.books[?(@.price >= 12.99)].title * Filter books that have a price less or equal to 12.99 * * @throws JSONPathException */ public function testQueryMatchEqualOrMore(): void { $result = (new JSONPath($this->getData('example'))) ->find('$.store.books[?(@.price >= 12.99)].title'); self::assertEquals(['Sword of Honour', 'The Lord of the Rings'], $result->getData()); } /** * $..books[?(@.author == "J. R. R. Tolkien")] * Filter books that have an author equal to "..." * * @throws JSONPathException */ public function testQueryMatchEquals(): void { $result = (new JSONPath($this->getData('example'))) ->find('$..books[?(@.author == "J. R. R. Tolkien")].title'); self::assertEquals('The Lord of the Rings', $result[0]); } /** * $..books[?(@.author = 1)] * Filter books that have a title equal to "..." * * @throws JSONPathException */ public function testQueryMatchEqualsWithUnquotedInteger(): void { $results = (new JSONPath($this->getData('simple-integers'))) ->find('$..features[?(@.value = 1)]'); self::assertEquals('foo', $results[0]->name); self::assertEquals('baz', $results[1]->name); } /** * $..books[?(@.author != "J. R. R. Tolkien")] * Filter books that have an author not equal to "..." * * @throws JSONPathException */ public function testQueryMatchNotEqualsTo(): void { $jsonPath = (new JSONPath($this->getData('example'))); $results = $jsonPath ->find('$..books[?(@.author != "J. R. R. Tolkien")].title'); self::assertcount(3, $results); self::assertEquals(['Sayings of the Century', 'Sword of Honour', 'Moby Dick'], $results->getData()); $results = $jsonPath ->find('$..books[?(@.author !== "J. R. R. Tolkien")].title'); self::assertcount(3, $results); self::assertEquals(['Sayings of the Century', 'Sword of Honour', 'Moby Dick'], $results->getData()); $results = $jsonPath ->find('$..books[?(@.author <> "J. R. R. Tolkien")].title'); self::assertcount(3, $results); self::assertEquals(['Sayings of the Century', 'Sword of Honour', 'Moby Dick'], $results->getData()); } /** * $..books[?(@.author =~ /nigel ree?s/i)] * Filter books where author matches regex * * @throws JSONPathException */ public function testQueryMatchWithRegexCaseSensitive(): void { $jsonPath = (new JSONPath($this->getData('example'))); $results = $jsonPath ->find('$..books[?(@.author =~ /nigel ree?s/i)].title'); self::assertcount(1, $results); self::assertEquals(['Sayings of the Century'], $results->getData()); $results = $jsonPath ->find('$..books[?(@.title =~ /^(Say|The).*/)].title'); self::assertcount(2, $results); self::assertEquals(['Sayings of the Century', 'The Lord of the Rings'], $results->getData()); } /** * $..books[?(@.author =~ "J. R. R. Tolkien")] * Filter books where author matches invalid regex * * @throws JSONPathException */ public function testQueryMatchWithInvalidRegex(): void { $result = (new JSONPath($this->getData('example'))) ->find('$..books[?(@.author =~ "J. R. R. Tolkien")].title'); self::assertEmpty($result->getData()); } /** * $..books[?(@.author in ["J. R. R. Tolkien", "Nigel Rees"])] * Filter books that have a title in ["...", "..."] * * @throws JSONPathException */ public function testQueryMatchIn(): void { $results = (new JSONPath($this->getData('example'))) ->find('$..books[?(@.author in ["J. R. R. Tolkien", "Nigel Rees"])].title'); self::assertEquals(['Sayings of the Century', 'The Lord of the Rings'], $results->getData()); } /** * $..books[?(@.author nin ["J. R. R. Tolkien", "Nigel Rees"])] * Filter books that don't have a title in ["...", "..."] * * @throws JSONPathException */ public function testQueryMatchNin(): void { $results = (new JSONPath($this->getData('example'))) ->find('$..books[?(@.author nin ["J. R. R. Tolkien", "Nigel Rees"])].title'); self::assertEquals(['Sword of Honour', 'Moby Dick'], $results->getData()); } /** * $..books[?(@.author nin ["J. R. R. Tolkien", "Nigel Rees"])] * Filter books that don't have a title in ["...", "..."] * * @throws JSONPathException */ public function testQueryMatchNotIn(): void { $results = (new JSONPath($this->getData('example'))) ->find('$..books[?(@.author !in ["J. R. R. Tolkien", "Nigel Rees"])].title'); self::assertEquals(['Sword of Honour', 'Moby Dick'], $results->getData()); } /** * $.store.books[*].author * * @throws JSONPathException */ public function testWildcardAltNotation(): void { $results = (new JSONPath($this->getData('example'))) ->find('$.store.books[*].author'); self::assertEquals(['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien'], $results->getData()); } /** * $..author * * @throws JSONPathException */ public function testRecursiveChildSearch(): void { $result = (new JSONPath($this->getData('example'))) ->find('$..author'); self::assertEquals(['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien'], $result->getData()); } /** * $.store.* * all things in store * the structure of the example data makes this test look weird * * @throws JSONPathException */ public function testWildCard(): void { $result = (new JSONPath($this->getData('example'))) ->find('$.store.*'); if (is_object($result[0][0])) { self::assertEquals('Sayings of the Century', $result[0][0]->title); } else { self::assertEquals('Sayings of the Century', $result[0][0]['title']); } if (is_object($result[1])) { self::assertEquals('red', $result[1]->color); } else { self::assertEquals('red', $result[1]['color']); } } /** * $.store..price * the price of everything in the store. * * @throws JSONPathException */ public function testRecursiveChildSearchAlt(): void { $result = (new JSONPath($this->getData('example'))) ->find('$.store..price'); self::assertEquals([8.95, 12.99, 8.99, 22.99, 19.95], $result->getData()); } /** * $..books[2] * the third book * * @throws JSONPathException */ public function testRecursiveChildSearchWithChildIndex(): void { $result = (new JSONPath($this->getData('example'))) ->find('$..books[2].title'); self::assertEquals(['Moby Dick'], $result->getData()); } /** * $..books[(@.length-1)] * * @throws JSONPathException */ public function testRecursiveChildSearchWithChildQuery(): void { $result = (new JSONPath($this->getData('example'))) ->find('$..books[(@.length-1)].title'); self::assertEquals(['The Lord of the Rings'], $result->getData()); } /** * $..books[-1:] * Return the last results * * @throws JSONPathException */ public function testRecursiveChildSearchWithSliceFilter(): void { $result = (new JSONPath($this->getData('example'))) ->find('$..books[-1:].title'); self::assertEquals(['The Lord of the Rings'], $result->getData()); } /** * $..books[?(@.isbn)] * filter all books with isbn number * * @throws JSONPathException */ public function testRecursiveWithQueryMatch(): void { $result = (new JSONPath($this->getData('example'))) ->find('$..books[?(@.isbn)].isbn'); self::assertEquals(['0-553-21311-3', '0-395-19395-8'], $result->getData()); } /** * .data.tokens[?(@.Employee.FirstName)] * Verify that it is possible to filter with a key containing punctuation * * @throws JSONPathException */ public function testRecursiveWithQueryMatchWithDots(): void { $result = (new JSONPath($this->getData('with-dots'))) ->find(".data.tokens[?(@.Employee.FirstName)]"); $result = json_decode(json_encode($result), true); self::assertEquals([['Employee.FirstName' => 'Jack']], $result); } /** * $..* * All members of JSON structure * * @throws JSONPathException */ public function testRecursiveWithWildcard(): void { $result = (new JSONPath($this->getData('example'))) ->find('$..*'); $result = json_decode(json_encode($result), true); self::assertEquals('Sayings of the Century', $result[0]['books'][0]['title']); self::assertEquals(19.95, $result[27]); } /** * Tests direct key access. * * @throws JSONPathException */ public function testSimpleArrayAccess(): void { $result = (new JSONPath(['title' => 'test title'])) ->find('title'); self::assertEquals(['test title'], $result->getData()); } /** * @throws JSONPathException */ public function testFilteringOnNoneArrays(): void { $result = (new JSONPath(['foo' => 'asdf'])) ->find('$.foo.bar'); self::assertEquals([], $result->getData()); } /** * @throws JSONPathException */ public function testMagicMethods(): void { $fooClass = new JSONPathTestClass(); $results = (new JSONPath($fooClass, JSONPath::ALLOW_MAGIC))->find('$.foo'); self::assertEquals(['bar'], $results->getData()); } /** * @throws JSONPathException */ public function testMatchWithComplexSquareBrackets(): void { $result = (new JSONPath($this->getData('extra'))) ->find("$['http://www.w3.org/2000/01/rdf-schema#label'][?(@['@language']='en')]['@language']"); self::assertEquals(["en"], $result->getData()); } /** * @throws JSONPathException */ public function testQueryMatchWithRecursive(): void { $result = (new JSONPath($this->getData('locations'))) ->find("..[?(@.type == 'suburb')].name"); self::assertEquals(["Rosebank"], $result->getData()); } /** * @throws JSONPathException */ public function testFirst(): void { $result = (new JSONPath($this->getData('extra'))) ->find("$['http://www.w3.org/2000/01/rdf-schema#label'].*"); self::assertEquals(["@language" => "en"], $result->first()->getData()); } /** * @throws JSONPathException */ public function testLast(): void { $result = (new JSONPath($this->getData('extra'))) ->find("$['http://www.w3.org/2000/01/rdf-schema#label'].*"); self::assertEquals(["@language" => "de"], $result->last()->getData()); } /** * @throws JSONPathException */ public function testSlashesInIndex(): void { $result = (new JSONPath($this->getData('with-slashes'))) ->find("$['mediatypes']['image/png']"); self::assertEquals(["/core/img/filetypes/image.png"], $result->getData()); } /** * @throws JSONPathException */ public function testUnionWithKeys(): void { $result = (new JSONPath( [ "key" => "value", "another" => "entry", ] ))->find("$['key','another']"); self::assertEquals(["value", "entry"], $result->getData()); } /** * @throws JSONPathException */ public function testCyrillicText(): void { $jsonPath = (new JSONPath(["???????" => 1])); $result = $jsonPath ->find("$['???????']"); self::assertEquals([1], $result->getData()); $result = $jsonPath ->find("$.???????"); self::assertEquals([1], $result->getData()); } public function testOffsetUnset(): void { $jsonIterator = new JSONPath( [ "route" => [ ["name" => "A", "type" => "type of A"], ["name" => "B", "type" => "type of B"], ], ] ); /** @var JSONPath $route */ $route = $jsonIterator->offsetGet('route'); $route->offsetUnset(0); $first = $route->first(); self::assertEquals("B", $first['name']); } public function testFirstKey(): void { // Array test for array $firstKey = (new JSONPath(['a' => 'A', 'b', 'B']))->firstKey(); self::assertEquals('a', $firstKey); // Array test for object $firstKey = (new JSONPath((object)['a' => 'A', 'b', 'B']))->firstKey(); self::assertEquals('a', $firstKey); } public function testLastKey(): void { // Array test for array $lastKey = (new JSONPath(['a' => 'A', 'b' => 'B', 'c' => 'C']))->lastKey(); self::assertEquals('c', $lastKey); // Array test for object $lastKey = (new JSONPath((object)['a' => 'A', 'b' => 'B', 'c' => 'C']))->lastKey(); self::assertEquals('c', $lastKey); } /** * Test: ensure trailing comma is stripped during parsing * * @throws JSONPathException */ public function testTrailingComma(): void { $result = (new JSONPath($this->getData('example'))) ->find("$..books[0,1,2,]"); self::assertCount(3, $result); } /** * Test: ensure negative indexes return -n from last index * * @throws JSONPathException */ public function testNegativeIndex(): void { $result = (new JSONPath($this->getData('example'))) ->find('$..books[-2]'); self::assertEquals("Herman Melville", $result[0]['author']); } /** * @throws JSONPathException */ public function testQueryAccessWithNumericalIndexes(): void { $result = (new JSONPath($this->getData('numerical-indexes-object'))) ->find("$.result.list[?(@.o == \"11.51000\")]"); self::assertEquals("11.51000", $result[0]->o); $result = (new JSONPath($this->getData('numerical-indexes-array'))) ->find("$.result.list[?(@[1] == \"11.51000\")]"); self::assertEquals("11.51000", $result[0][1]); } }