diff --git a/src/Pointers/Pointer.php b/src/Pointers/Pointer.php index 43bf9bc..b553cb3 100644 --- a/src/Pointers/Pointer.php +++ b/src/Pointers/Pointer.php @@ -113,7 +113,7 @@ final class Pointer implements Stringable * @param mixed $key * @return mixed */ - public function call(mixed $value, mixed $key): mixed + public function call(mixed $value, mixed &$key): mixed { if ($this->callback === null) { return $value; diff --git a/src/ValueObjects/State.php b/src/ValueObjects/State.php index e88da0a..15fc273 100644 --- a/src/ValueObjects/State.php +++ b/src/ValueObjects/State.php @@ -51,7 +51,7 @@ final class State */ public function __construct(private Pointers $pointers, private Closure $lazyLoad) { - $this->tree = new Tree($this->pointers); + $this->tree = new Tree($pointers); } /** @@ -91,7 +91,7 @@ final class State * @param mixed $key * @return mixed */ - public function callPointer(mixed $value, mixed $key): mixed + public function callPointer(mixed $value, mixed &$key): mixed { return $this->pointers->matching()->call($value, $key); } @@ -107,11 +107,15 @@ final class State $this->tree->traverseToken($token, $this->expectsKey); if ($this->tree->isMatched() && ((!$this->expectsKey && $token->isValue()) || $this->tree->isDeep())) { - $shouldLazyLoad = $token instanceof CompoundBegin && $this->pointers->matching()->isLazy(); - /** @phpstan-ignore-next-line */ - $this->buffer = $shouldLazyLoad ? ($this->lazyLoad)() : $this->buffer . $token; - /** @var CompoundBegin $token */ - $shouldLazyLoad && $token->shouldLazyLoad = true; + $this->pointers->markAsFound(); + + if ($token instanceof CompoundBegin && $this->pointers->matching()->isLazy()) { + $this->buffer = ($this->lazyLoad)(); + $token->shouldLazyLoad = true; + } else { + /** @phpstan-ignore-next-line */ + $this->buffer .= $token; + } } $token->mutateState($this); diff --git a/tests/Dataset.php b/tests/Dataset.php index 351c89a..18b0545 100644 --- a/tests/Dataset.php +++ b/tests/Dataset.php @@ -96,6 +96,23 @@ final class Dataset yield from self::forSinglePointersWithFixture('pointers/single_pointer_to_array.php'); } + /** + * Retrieve the dataset to test the key update + * + * @return Generator + */ + public static function forKeyUpdate(): Generator + { + $json = fixture('json/complex_object.json'); + $pointers = [ + '/type' => function ($value, &$key) { + $key = 'foo'; + }, + ]; + + yield [$json, $pointers, ['foo' => 'donut']]; + } + /** * Retrieve the dataset to test multiple pointers * diff --git a/tests/Feature/PointersTest.php b/tests/Feature/PointersTest.php index d7d7298..1f10475 100644 --- a/tests/Feature/PointersTest.php +++ b/tests/Feature/PointersTest.php @@ -23,6 +23,10 @@ it('eager loads lazy pointers into an array', function (string $json, string $po expect(JsonParser::parse($json)->lazyPointer($pointer)->toArray())->toBe($expected); })->with(Dataset::forSinglePointersToArray()); +it('can modify key and value of a pointer', function (string $json, array $pointers, array $expected) { + expect(JsonParser::parse($json)->pointers($pointers)->toArray())->toBe($expected); +})->with(Dataset::forKeyUpdate()); + it('loads JSON from multiple JSON pointers', function (string $json, array $pointers, array $parsed) { expect(JsonParser::parse($json)->pointers($pointers))->toPointTo($parsed); })->with(Dataset::forMultiplePointers());