{"id":52054101,"url":"https://github.com/bumpcore/json-patch","last_synced_at":"2026-08-02T16:01:24.272Z","repository":{"id":366893048,"uuid":"1236412687","full_name":"bumpcore/json-patch","owner":"bumpcore","description":"RFC 6902 JSON Patch and RFC 7396 JSON Merge Patch implementation for PHP.","archived":false,"fork":false,"pushed_at":"2026-05-21T12:03:22.000Z","size":61,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"0.x","last_synced_at":"2026-06-23T20:05:07.201Z","etag":null,"topics":["json-merge","json-patch","php"],"latest_commit_sha":null,"homepage":"https://bumpcore.com/docs/json-patch","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bumpcore.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-12T08:15:53.000Z","updated_at":"2026-05-30T00:36:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bumpcore/json-patch","commit_stats":null,"previous_names":["bumpcore/json-patch"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/bumpcore/json-patch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bumpcore%2Fjson-patch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bumpcore%2Fjson-patch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bumpcore%2Fjson-patch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bumpcore%2Fjson-patch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bumpcore","download_url":"https://codeload.github.com/bumpcore/json-patch/tar.gz/refs/heads/0.x","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bumpcore%2Fjson-patch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36199567,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-08-02T02:00:06.915Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json-merge","json-patch","php"],"created_at":"2026-08-02T16:01:22.465Z","updated_at":"2026-08-02T16:01:24.113Z","avatar_url":"https://github.com/bumpcore.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BumpCore JSON Patch\n\nBumpCore JSON Patch is a dependency-free PHP package for working with JSON\nchange documents. It supports RFC 6902 JSON Patch, RFC 7396 JSON Merge Patch,\nand RFC 6901 JSON Pointer.\n\nUse it when you need to apply HTTP PATCH payloads, generate deterministic patch\ndocuments, address values inside JSON-like PHP data, or expose precise patch\nerrors to API clients.\n\n## Table Of Contents\n\n* [Version Table](#version-table)\n* [Installation](#installation)\n* [Quick Start](#quick-start)\n* [Choosing a Patch Format](#choosing-a-patch-format)\n* [JSON Patch](#json-patch)\n  + [Applying JSON Patch Documents](#applying-json-patch-documents)\n  + [Generating JSON Patch Documents](#generating-json-patch-documents)\n  + [Supported Operations](#supported-operations)\n* [JSON Merge Patch](#json-merge-patch)\n* [JSON Pointer](#json-pointer)\n* [JSON Values in PHP](#json-values-in-php)\n* [Exceptions](#exceptions)\n* [Testing](#testing)\n* [Contribution](#contribution)\n* [Changelog](#changelog)\n* [Credits](#credits)\n* [License](#license)\n\n## Version Table\n\n| BumpCore JSON Patch | PHP  |\n|---------------------|------|\n| 0.x                 | ^8.3 |\n\n## Installation\n\nInstall the package with Composer:\n\n```bash\ncomposer require bumpcore/json-patch\n```\n\n## Quick Start\n\n```php\nuse BumpCore\\JsonPatch\\JsonPatch;\n\n$document = ['foo' =\u003e ['bar', 'baz']];\n\n$result = JsonPatch::apply($document, [\n    ['op' =\u003e 'add', 'path' =\u003e '/foo/1', 'value' =\u003e 'qux'],\n]);\n\n// ['foo' =\u003e ['bar', 'qux', 'baz']]\n```\n\nFor JSON string input and output:\n\n```php\nuse BumpCore\\JsonPatch\\JsonPatch;\n\n$json = JsonPatch::applyJson(\n    '{\"foo\":[\"bar\",\"baz\"]}',\n    '[{\"op\":\"add\",\"path\":\"/foo/1\",\"value\":\"qux\"}]',\n);\n\n// {\"foo\":[\"bar\",\"qux\",\"baz\"]}\n```\n\n## Choosing a Patch Format\n\nThis package supports two patch formats because they solve different problems.\n\nUse **JSON Patch** when you need explicit operations:\n\n```json\n[\n  {\"op\": \"replace\", \"path\": \"/title\", \"value\": \"Hello!\"},\n  {\"op\": \"remove\", \"path\": \"/author/familyName\"}\n]\n```\n\nUse **JSON Merge Patch** when the patch should look like the document shape:\n\n```json\n{\n  \"title\": \"Hello!\",\n  \"author\": {\n    \"familyName\": null\n  }\n}\n```\n\nJSON Patch can update individual array elements. JSON Merge Patch replaces\narrays as whole values and uses `null` object members as removals.\n\n## JSON Patch\n\n`JsonPatch` implements RFC 6902.\n\n### Applying JSON Patch Documents\n\n```php\nuse BumpCore\\JsonPatch\\JsonPatch;\n\n$document = [\n    'title' =\u003e 'Goodbye!',\n    'tags' =\u003e ['example', 'sample'],\n];\n\n$patched = JsonPatch::apply($document, [\n    ['op' =\u003e 'replace', 'path' =\u003e '/title', 'value' =\u003e 'Hello!'],\n    ['op' =\u003e 'remove', 'path' =\u003e '/tags/1'],\n    ['op' =\u003e 'add', 'path' =\u003e '/published', 'value' =\u003e true],\n]);\n\n// [\n//     'title' =\u003e 'Hello!',\n//     'tags' =\u003e ['example'],\n//     'published' =\u003e true,\n// ]\n```\n\nPatch application does not mutate the input document. It stops at the first\nfailing operation, as RFC 6902 requires.\n\n### Generating JSON Patch Documents\n\n```php\nuse BumpCore\\JsonPatch\\JsonPatch;\n\n$source = ['name' =\u003e 'old', 'tags' =\u003e ['stable']];\n$target = ['name' =\u003e 'new', 'tags' =\u003e ['stable', 'fast']];\n\n$patch = JsonPatch::diff($source, $target);\n\n// [\n//     ['op' =\u003e 'replace', 'path' =\u003e '/name', 'value' =\u003e 'new'],\n//     ['op' =\u003e 'add', 'path' =\u003e '/tags/-', 'value' =\u003e 'fast'],\n// ]\n```\n\n`JsonPatch::diff()` generates readable `add`, `remove`, and `replace`\noperations. It intentionally does not infer `move` or `copy` operations because\nthose require heuristic choices and can make generated patches harder to review.\n\nFor JSON text input and output:\n\n```php\nuse BumpCore\\JsonPatch\\JsonPatch;\n\n$patchJson = JsonPatch::diffJson(\n    '{\"name\":\"old\"}',\n    '{\"name\":\"new\",\"enabled\":true}',\n);\n\n// [{\"op\":\"add\",\"path\":\"/enabled\",\"value\":true},{\"op\":\"replace\",\"path\":\"/name\",\"value\":\"new\"}]\n```\n\n### Supported Operations\n\n* `add`\n* `remove`\n* `replace`\n* `move`\n* `copy`\n* `test`\n\nThe package exposes the RFC media type:\n\n```php\nJsonPatch::MEDIA_TYPE; // application/json-patch+json\n```\n\n## JSON Merge Patch\n\n`JsonMergePatch` implements RFC 7396.\n\n```php\nuse BumpCore\\JsonPatch\\JsonMergePatch;\n\n$document = [\n    'title' =\u003e 'Goodbye!',\n    'author' =\u003e [\n        'givenName' =\u003e 'John',\n        'familyName' =\u003e 'Doe',\n    ],\n    'tags' =\u003e ['example', 'sample'],\n];\n\n$patched = JsonMergePatch::apply($document, [\n    'title' =\u003e 'Hello!',\n    'author' =\u003e [\n        'familyName' =\u003e null,\n    ],\n    'tags' =\u003e ['example'],\n]);\n\n// [\n//     'title' =\u003e 'Hello!',\n//     'author' =\u003e ['givenName' =\u003e 'John'],\n//     'tags' =\u003e ['example'],\n// ]\n```\n\nMerge Patch rules are intentionally simple:\n\n* Object members are added or replaced.\n* Object members set to `null` are removed.\n* Arrays are replaced as whole values.\n* Non-object patches replace the whole target document.\n\nFor JSON text input and output:\n\n```php\nuse BumpCore\\JsonPatch\\JsonMergePatch;\n\n$json = JsonMergePatch::applyJson(\n    '{\"a\":\"b\",\"c\":{\"d\":\"e\",\"f\":\"g\"}}',\n    '{\"a\":\"z\",\"c\":{\"f\":null}}',\n);\n\n// {\"a\":\"z\",\"c\":{\"d\":\"e\"}}\n```\n\nThe package exposes the RFC media type:\n\n```php\nJsonMergePatch::MEDIA_TYPE; // application/merge-patch+json\n```\n\n## JSON Pointer\n\n`JsonPointer` implements RFC 6901 pointer parsing and escaping.\n\n```php\nuse BumpCore\\JsonPatch\\JsonPointer;\n\n$pointer = JsonPointer::fromString('/foo/~01');\n\n$pointer-\u003etokens(); // ['foo', '~1']\nJsonPointer::escapeToken('a/b~c'); // a~1b~0c\nJsonPointer::unescapeToken('a~1b~0c'); // a/b~c\n```\n\nPointer helpers can also read and return modified copies of JSON-like values:\n\n```php\nuse BumpCore\\JsonPatch\\JsonPointer;\n\n$document = ['items' =\u003e [['name' =\u003e 'Old']]];\n\nJsonPointer::get($document, '/items/0/name'); // Old\nJsonPointer::has($document, '/items/0/name'); // true\n\n$updated = JsonPointer::set($document, '/items/0/name', 'New');\n$removed = JsonPointer::remove($updated, '/items/0');\n```\n\nThe helper methods do not mutate the original document.\n\n## JSON Values in PHP\n\nThe PHP-value APIs accept JSON-like PHP data:\n\n* PHP lists are treated as JSON arrays.\n* `stdClass` objects are treated as JSON objects.\n* Non-list PHP arrays are treated as JSON objects for ergonomic PHP usage.\n* Non-finite floats and non-JSON PHP values are rejected.\n\nWhen exact JSON shape matters, especially empty objects or numeric object member\nnames, use the JSON string helpers:\n\n```php\nuse BumpCore\\JsonPatch\\JsonPatch;\n\n$json = JsonPatch::applyJson(\n    '{\"child\":{}}',\n    '[{\"op\":\"add\",\"path\":\"/child/0\",\"value\":\"kept as an object member\"}]',\n);\n\n// {\"child\":{\"0\":\"kept as an object member\"}}\n```\n\n## Exceptions\n\nAll package-specific failures extend:\n\n```php\nBumpCore\\JsonPatch\\Exception\\JsonPatchException\n```\n\nMore specific exceptions are available:\n\n* `InvalidPatchException`\n* `JsonPointerException`\n* `TestFailedException`\n\nPatch operation failures expose context when it is available:\n\n```php\n$exception-\u003eoperationIndex(); // 0\n$exception-\u003eoperation(); // remove\n$exception-\u003epath(); // /items/0\n$exception-\u003efrom(); // /source for move/copy failures\n```\n\n## Testing\n\nInstall development dependencies:\n\n```bash\ncomposer install\n```\n\nRun the test suite:\n\n```bash\ncomposer test\n```\n\nRun static analysis:\n\n```bash\ncomposer analyse\n```\n\nCheck code style:\n\n```bash\ncomposer cs:check\n```\n\nRun the 100% coverage gate:\n\n```bash\ncomposer test:coverage\n```\n\nThe test suite includes the active upstream `json-patch/json-patch-tests`\nfixtures. Coverage requires PCOV, Xdebug, or phpdbg.\n\n## Contribution\n\nContributions are welcome. If you find a bug or have a suggestion for\nimprovement, please open an issue or create a pull request.\n\nPlease include tests for behavioral changes and run the quality checks before\nsubmitting a pull request:\n\n```bash\ncomposer cs:check\ncomposer analyse\ncomposer test\n```\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for version history.\n\n## Credits\n\n* [Abdulkadir Cemiloglu](https://github.com/megastive19)\n* [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbumpcore%2Fjson-patch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbumpcore%2Fjson-patch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbumpcore%2Fjson-patch/lists"}