{"id":522,"library":"jsonpatch","title":"JSON Patch","description":"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.","status":"active","version":"1.33","language":"python","source_language":"en","source_url":"https://github.com/stefankoegl/python-json-patch","tags":["json","patch","rfc6902","document-manipulation"],"install":[{"cmd":"pip install jsonpatch","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"symbol":"JsonPatch","correct":"from jsonpatch import JsonPatch"},{"note":"Raised when a patch operation encounters a conflict or error.","symbol":"JsonPointerException","correct":"from jsonpatch import JsonPointerException"},{"note":"A convenience function to apply a patch to a document.","symbol":"apply_patch","correct":"from jsonpatch import apply_patch"},{"note":"A convenience function to generate a patch by diffing two documents.","symbol":"make_patch","correct":"from jsonpatch import make_patch"}],"quickstart":{"code":"import jsonpatch\n\n# Original document\ndoc = {\"baz\": \"qux\", \"foo\": \"bar\", \"numbers\": [1, 3, 4, 8]}\n\n# 1. Define a patch explicitly\npatch_ops = [\n    {\"op\": \"replace\", \"path\": \"/baz\", \"value\": \"boo\"},\n    {\"op\": \"add\", \"path\": \"/hello\", \"value\": [\"world\"]},\n    {\"op\": \"remove\", \"path\": \"/foo\"},\n    {\"op\": \"replace\", \"path\": \"/numbers/0\", \"value\": 0}, # Replace first element\n    {\"op\": \"add\", \"path\": \"/numbers/-\", \"value\": 99} # Add to end of array\n]\npatch = jsonpatch.JsonPatch(patch_ops)\n\n# Apply the patch (returns a new object by default)\nresult = patch.apply(doc)\nprint(\"1. Applied patch result:\", result)\n# Expected: {'baz': 'boo', 'numbers': [0, 3, 4, 8, 99], 'hello': ['world']}\n\n# 2. Generate a patch by diffing two objects\nold_doc = {\"a\": 1, \"b\": 2, \"c\": {\"d\": 3}}\nnew_doc = {\"a\": 10, \"c\": {\"e\": 5}, \"f\": 6}\ndiff_patch = jsonpatch.make_patch(old_doc, new_doc)\nprint(\"2. Generated diff patch operations:\", diff_patch.patch)\n# Expected operations will modify old_doc to become new_doc.","lang":"python","description":"This quickstart demonstrates how to create a `JsonPatch` object from a list of operations and apply it to a document, as well as how to use `make_patch` to generate a patch by comparing two documents. The `apply` method returns a new modified document by default."},"warnings":[{"fix":"Use `result = patch.apply(original_doc)` for a new object, or `patch.apply(original_doc, in_place=True)` to modify the original.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure JSON Pointers correctly escape special characters in path segments (e.g., `/foo~1bar` for key `foo/bar`) and use `\"\"` for the document root.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For `add` to end of array, use `/array/-`. For `remove`/`replace`, use explicit indices like `/array/0`. Be mindful of array stability when patching by index.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Implement robust error handling for `JsonPointerException` when applying patches. If modifying in-place, consider applying patches within a transaction or to a copy first if atomicity is critical.","message":"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.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T14:37:45.002Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"Install the library using pip: `pip install jsonpatch`","cause":"The 'jsonpatch' Python package is not installed in your current environment or is not accessible in your Python path.","error":"ModuleNotFoundError: No module named 'jsonpatch'"},{"fix":"Ensure the object you are calling `.items()` on is a dictionary. If it's a list of dictionaries, iterate through the list and apply `.items()` to each dictionary: `for item in my_list: for key, value in item.items(): ...`","cause":"This error occurs when attempting to call the `.items()` method (which is designed for dictionaries) on a Python list object. This often happens when a JSON document is parsed into a list (e.g., a JSON array at the root) but is then treated as a dictionary, or when iterating over a list of dictionaries without accessing individual dictionary elements first.","error":"AttributeError: 'list' object has no attribute 'items'"},{"fix":"Review the patch operations and the target document. Ensure all paths specified in the patch exist or are valid for the intended operation (e.g., parent objects for 'add' operations must exist). Validate array indices and avoid attempting to add keys that already exist.","cause":"This general exception is raised by the `jsonpatch` library when an operation within the patch document cannot be successfully applied to the target JSON document. Common reasons include attempting to add a key that already exists, operating on a non-existent path (e.g., trying to modify a property whose parent object doesn't exist), or inserting a value into an array at an out-of-bounds position.","error":"jsonpatch.JsonPatchException: Patch could not be applied due to conflict situation"},{"fix":"Ensure all intermediate components of a JSON Pointer path exist in the target document before attempting operations like 'remove', 'replace', or 'test'. For 'add' operations, the *parent* path must exist; if intermediate objects need to be created, they must be added incrementally as separate operations.","cause":"This specific exception indicates that a JSON Pointer path used in a patch operation attempts to access a key or array index that does not exist in the target document. For instance, an 'add' operation might try to create a property at `/a/b/c` when `/a/b` does not exist.","error":"jsonpatch.JsonPointerException: Key 'nonexistent_key' not found in document"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.3,"disk_size":"17.9M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.3,"disk_size":"18M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":0.4,"disk_size":"19.7M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.4,"disk_size":"20M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":0.4,"disk_size":"11.6M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":0.4,"disk_size":"12M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.6,"disk_size":"11.2M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.4,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.3,"disk_size":"17.4M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.3,"disk_size":"18M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}