Skip to content

Latest commit

 

History

History
151 lines (104 loc) · 4.81 KB

File metadata and controls

151 lines (104 loc) · 4.81 KB

ALTO JSON Patch

Strict RFC 6902 patching and deterministic diffs for PHP.

  PHP Version   CI   Packagist   License   GitHub Sponsors

ALTO JSON Patch applies all six JSON Patch operations and generates stable patches between PHP values. Its identity-aware list diffing can express moves and nested changes instead of replacing complete lists, keeping generated patches compact and readable.

use Alto\JsonPatch\JsonPatch;

$before = ['status' => 'draft', 'tags' => ['php']];
$after = ['status' => 'published', 'tags' => ['php', 'json']];

$patch = JsonPatch::diff($before, $after);
$result = JsonPatch::apply($before, $patch);

assert($after === $result);

The package has no runtime dependencies beyond PHP's JSON extension. Its test suite includes the RFC 6902 compliance corpus, and the codebase is analyzed at PHPStan level 10.

Installation

Install ALTO JSON Patch with Composer:

composer require alto/json-patch

ALTO JSON Patch requires PHP 8.3 or later and the JSON extension. The extension ships with PHP.

Quick Start

Apply a sequence of operations to an in-memory value:

use Alto\JsonPatch\JsonPatch;

$document = [
    'user' => ['name' => 'Alice', 'role' => 'editor'],
    'status' => 'draft',
];

$patch = [
    ['op' => 'replace', 'path' => '/user/role', 'value' => 'admin'],
    ['op' => 'replace', 'path' => '/status', 'value' => 'published'],
];

$result = JsonPatch::apply($document, $patch);

The original value is unchanged. Operations run in order, and each operation sees the result of the preceding one.

Applying Patches

JsonPatch::apply() supports every RFC 6902 operation:

Operation Effect
add Insert or replace a value
remove Delete an existing value
replace Replace an existing value
move Move a value to another path
copy Copy a value to another path
test Assert that a value matches

Use JsonPatch::applyJson() to work directly with JSON strings. Read Applying patches for path rules, validation, JSON handling, and failures.

Generating Patches

Generate the operations needed to transform one state into another:

$patch = JsonPatch::diff(
    ['version' => 1, 'status' => 'draft'],
    ['version' => 2, 'status' => 'published'],
);

Object keys are compared recursively. Lists use a longest common subsequence by default, producing stable add and remove operations while preserving unchanged items.

Identity-aware Lists

Configure an identity key to express item moves and nested changes:

use Alto\JsonPatch\DiffOptions;

$options = new DiffOptions(
    listIdentityByPointer: ['/items' => 'id'],
);

$patch = JsonPatch::diff($before, $after, $options);

Read Generating patches for list strategies and their fallback behavior.

JSON Pointers

Patch paths follow RFC 6901. Use JsonPatch::get() and JsonPatch::test() to inspect values at a path, or Pointer when another component needs to parse and compose paths.

$name = JsonPatch::get($document, '/user/name');
$isAdmin = JsonPatch::test($document, '/user/role', 'admin');

Read JSON Pointers for root paths, list indices, and escaping. The complete guide also covers installation and a first end-to-end patch.

Contributing

Contributions of all kinds are welcome. Visit the project on GitHub to report a bug, suggest a feature, or open a pull request.

Before submitting code, run:

# Runs PHP CS Fixer, PHPStan, and PHPUnit
composer qa

Changes to public behavior should include tests and documentation.

Support

ALTO JSON Patch is open source. You can support its continued development through GitHub Sponsors.

Sharing this package with others or starring it on GitHub is also much appreciated.

License

ALTO JSON Patch is released by ALTO PHP under the MIT License.