JSON Patch
jsonpatch is a Python library for applying JSON Patches (RFC 6902), a standard format for describing changes to a JSON document. It provides functionalities to create, apply, and generate patches by diffing two JSON objects. The library is actively maintained, with its current version being 1.33.
Warnings
- gotcha The `apply` method returns a *new* modified object by default, leaving the original document unchanged. If you intend to modify the document in-place, you must explicitly pass `in_place=True` to the `apply` method.
- gotcha JSON Pointer (RFC 6901), used for `path` in operations, requires special characters `~` and `/` within object keys to be escaped as `~0` and `~1` respectively. Additionally, the empty string `""` refers to the root of the document, while `/` refers to a key named `""` at the root.
- gotcha When modifying arrays, `add` operations support the special character `-` in the path (e.g., `/array/-`) to append a value to the end of the array. However, `remove` or `replace` operations typically require a numeric index. Relying on fixed indices for modifications can be fragile if the array's order or content might change unpredictably between patch generation and application.
- gotcha JSON Patch operations are atomic. If any single operation within a patch document fails (e.g., a `test` operation fails, or a `remove` operation targets a non-existent path), a `jsonpatch.JsonPointerException` will be raised. If `in_place=False` (the default), no changes will be applied. If `in_place=True`, the state after an error is undefined and may be partially applied.
Install
-
pip install jsonpatch
Imports
- JsonPatch
from jsonpatch import JsonPatch
- JsonPointerException
from jsonpatch import JsonPointerException
- apply_patch
from jsonpatch import apply_patch
- make_patch
from jsonpatch import make_patch
Quickstart
import jsonpatch
# Original document
doc = {"baz": "qux", "foo": "bar", "numbers": [1, 3, 4, 8]}
# 1. Define a patch explicitly
patch_ops = [
{"op": "replace", "path": "/baz", "value": "boo"},
{"op": "add", "path": "/hello", "value": ["world"]},
{"op": "remove", "path": "/foo"},
{"op": "replace", "path": "/numbers/0", "value": 0}, # Replace first element
{"op": "add", "path": "/numbers/-", "value": 99} # Add to end of array
]
patch = jsonpatch.JsonPatch(patch_ops)
# Apply the patch (returns a new object by default)
result = patch.apply(doc)
print("1. Applied patch result:", result)
# Expected: {'baz': 'boo', 'numbers': [0, 3, 4, 8, 99], 'hello': ['world']}
# 2. Generate a patch by diffing two objects
old_doc = {"a": 1, "b": 2, "c": {"d": 3}}
new_doc = {"a": 10, "c": {"e": 5}, "f": 6}
diff_patch = jsonpatch.make_patch(old_doc, new_doc)
print("2. Generated diff patch operations:", diff_patch.patch)
# Expected operations will modify old_doc to become new_doc.