boundwize / jsonrecast
Editable JSON AST with visitor traversal and formatting-preserving printing.
Fund package maintenance!
1.0.17
2026-08-01 17:24 UTC
Requires
- php: ^8.2
Requires (Dev)
- boundwize/pyrameter: ^0.5
- boundwize/structarmed: ^0.15
- laminas/laminas-coding-standard: ^3.1
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11.5
- rector/rector: ^2.4
This package is auto-updated.
Last update: 2026-08-01 17:25:42 UTC
README
Editable JSON AST with visitor traversal and formatting-preserving printing.
Edit JSON content without noisy diffs
- Update JSON content programmatically and keep the original indentation, spacing, and key order intact.
- Transform documents with visitors, inspired by nikic/PHP-Parser, with path awareness built in.
- The printed output differs from the input only where you made changes; nothing else is reformatted.
Installation
composer require boundwize/jsonrecast
Example
Say we want to bump a dependency, add a new one, and remove an entry in composer.json. With JsonRecast, a single visitor does all three:
<?php use Boundwize\JsonRecast\JsonRecast; use Boundwize\JsonRecast\Node\NodeJson; use Boundwize\JsonRecast\Node\ObjectItemNode; use Boundwize\JsonRecast\Node\ObjectNode; use Boundwize\JsonRecast\Node\StringNode; use Boundwize\JsonRecast\NodePath\NodeJsonPath; use Boundwize\JsonRecast\NodeVisitor\NodeJsonVisitor; use Boundwize\JsonRecast\NodeVisitor\NodeJsonVisitorAbstract; $document = JsonRecast::parse(file_get_contents('composer.json')); $result = JsonRecast::traverse($document, new class extends NodeJsonVisitorAbstract { public function enterNode(NodeJson $node, NodeJsonPath $path): null|NodeJson|int { // ~ bump monolog to ^3.6 if ($node instanceof ObjectItemNode && $path->matches(['require']) && $node->key->value === 'monolog/monolog') { $node->value = new StringNode('^3.6'); return $node; } // + add guzzle under "require" if ($node instanceof ObjectNode && $path->matches(['require'])) { $node->set('guzzlehttp/guzzle', new StringNode('^7.8')); return $node; } // − drop the root "minimum-stability" entry if ($node instanceof ObjectItemNode && $path->isRoot() && $node->key->value === 'minimum-stability') { return NodeJsonVisitor::REMOVE_NODE; } return null; } }); // update the file with original formatting preserved file_put_contents('composer.json', JsonRecast::print($result));
Anything the visitor didn't touch keeps its original indentation, key order, and alignment.
Documentation
Documentation is available online, with source files kept in this repository:
- Documentation site: https://boundwize.github.io/jsonrecast/
- Documentation source: docs/ for local edits and GitHub Pages publishing.