From 0a89ee2cd37104f9a9bf3d65a13159eef4317829 Mon Sep 17 00:00:00 2001 From: Shahadat Islam Koyel <179203101+ShahadatTest@users.noreply.github.com> Date: Mon, 26 Oct 2026 23:05:33 +0600 Subject: [PATCH] Document whole-document results and root replacement --- doc/tutorial.rst | 42 +++++++++++++++++++++++++++++++++++++++++- jsonpatch.py | 32 +++++++++++++++++--------------- 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 1e89c7d..9328884 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -42,7 +42,7 @@ Another way is to *diff* two objects. Applying a Patch ---------------- -A patch is always applied to an object. The patch created by diffing ``src`` +A patch is applied to a JSON document. The patch created by diffing ``src`` and ``dst`` above turns ``src`` into ``dst``: .. code-block:: python @@ -83,6 +83,46 @@ explicitly. >>> res = jsonpatch.apply_patch(obj, patch) +Replacing the Whole Document +---------------------------- + +A document can be an object, array, string, number, boolean, or ``null``. +An empty ``path`` (``""``) selects the whole document, so a replacement can +also change its type: + +.. code-block:: python + + >>> import jsonpatch + >>> original = {'old': True} + >>> patch = jsonpatch.JsonPatch([ + ... {'op': 'replace', 'path': '', 'value': [1, 2]} + ... ]) + >>> result = patch.apply(original, in_place=True) + >>> result + [1, 2] + >>> original + {'old': True} + +Always use the return value when an operation can replace the root, even +with ``in_place=True``. Replacing the root returns a new value; it cannot +rebind the caller's variable. Changes to members of the original container +can still happen in place. + +The empty pointer differs from ``"/"``, which selects an object member +whose key is the empty string: + +.. code-block:: python + + >>> jsonpatch.apply_patch({'': 1}, [ + ... {'op': 'replace', 'path': '/', 'value': 2} + ... ]) + {'': 2} + >>> jsonpatch.apply_patch(None, [ + ... {'op': 'add', 'path': '', 'value': False} + ... ]) + False + + Paths and Special Characters ---------------------------- diff --git a/jsonpatch.py b/jsonpatch.py index 71e131c..918d5c3 100644 --- a/jsonpatch.py +++ b/jsonpatch.py @@ -102,8 +102,8 @@ def multidict(ordered_pairs): def apply_patch(doc, patch, in_place=False, pointer_cls=JsonPointer): """Apply list of patches to specified json document. - :param doc: Document object. - :type doc: dict + :param doc: JSON document, including arrays and scalar values. + :type doc: object :param patch: JSON patch as list of dicts or raw JSON-encoded string. :type patch: list or str @@ -115,8 +115,8 @@ def apply_patch(doc, patch, in_place=False, pointer_cls=JsonPointer): :param pointer_cls: JSON pointer class to use. :type pointer_cls: Type[JsonPointer] - :return: Patched document object. - :rtype: dict + :return: Resulting document, which may have a different type from ``doc``. + :rtype: object >>> doc = {'foo': 'bar'} >>> patch = [{'op': 'add', 'path': '/baz', 'value': 'qux'}] @@ -145,11 +145,11 @@ def make_patch(src, dst, pointer_cls=JsonPointer): transforms `src` into `dst`, so it has to be applied to `src` (or to a document equal to it). - :param src: Data source document object. - :type src: dict + :param src: Source JSON document, including arrays and scalar values. + :type src: object - :param dst: Data target document object. - :type dst: dict + :param dst: Target JSON document, including arrays and scalar values. + :type dst: object :param pointer_cls: JSON pointer class to use. :type pointer_cls: Type[JsonPointer] @@ -598,11 +598,11 @@ def from_diff( one. The resulting patch transforms `src` into `dst`, so it has to be applied to `src` (or to a document equal to it). - :param src: Data source document object. - :type src: dict + :param src: Source JSON document, including arrays and scalar values. + :type src: object - :param dst: Data target document object. - :type dst: dict + :param dst: Target JSON document, including arrays and scalar values. + :type dst: object :param optimization: Generate move operations for matching values. Set to False to use only add, remove and replace. @@ -643,14 +643,16 @@ def _ops(self): def apply(self, obj, in_place=False): """Applies the patch to a given object. - :param obj: Document object. - :type obj: dict + :param obj: JSON document, including arrays and scalar values. + :type obj: object :param in_place: Tweaks the way how patch would be applied - directly to specified `obj` or to its copy. :type in_place: bool - :return: Modified `obj`. + :return: Resulting document. Use this return value even with + ``in_place=True``, because a root replacement returns a new + value rather than modifying the original container. """ if not in_place: