Tutorial

Please refer to RFC 6902 for the exact patch syntax.

Creating a Patch

Patches can be created in two ways. One way is to explicitly create a JsonPatch object from a list of operations. For convenience, the method JsonPatch.from_string() accepts a string, parses it and constructs the patch object from it.

>>> import jsonpatch
>>> patch = jsonpatch.JsonPatch([
    {'op': 'add', 'path': '/foo', 'value': 'bar'},
    {'op': 'add', 'path': '/baz', 'value': [1, 2, 3]},
    {'op': 'remove', 'path': '/baz/1'},
    {'op': 'test', 'path': '/baz', 'value': [1, 3]},
    {'op': 'replace', 'path': '/baz/0', 'value': 42},
    {'op': 'remove', 'path': '/baz/1'},
])

# or equivalently
>>> patch = jsonpatch.JsonPatch.from_string('[{"op": "add", ....}]')

Another way is to diff two objects.

>>> src = {'foo': 'bar', 'numbers': [1, 3, 4, 8]}
>>> dst = {'baz': 'qux', 'numbers': [1, 4, 7]}
>>> patch = jsonpatch.JsonPatch.from_diff(src, dst)

# or equivalently
>>> patch = jsonpatch.make_patch(src, dst)

Applying a Patch

A patch is always applied to an object.

>>> doc = {}
>>> result = patch.apply(doc)
{'foo': 'bar', 'baz': [42]}

The apply method returns a new object as a result. If in_place=True the object is modified in place.

If a patch is only used once, it is not necessary to create a patch object explicitly.

>>> obj = {'foo': 'bar'}

# from a patch string
>>> patch = '[{"op": "add", "path": "/baz", "value": "qux"}]'
>>> res = jsonpatch.apply_patch(obj, patch)

# or from a list
>>> patch = [{'op': 'add', 'path': '/baz', 'value': 'qux'}]
>>> res = jsonpatch.apply_patch(obj, patch)

Dealing with Custom Types

Custom JSON dump and load functions can be used to support custom types such as decimal.Decimal. The following examples shows how the simplejson package, which has native support for Python’s Decimal type, can be used to create a custom JsonPatch subclass with Decimal support:

>>> import decimal
>>> import simplejson

>>> class DecimalJsonPatch(jsonpatch.JsonPatch):
        @staticmethod
        def json_dumper(obj):
            return simplejson.dumps(obj)

        @staticmethod
        def json_loader(obj):
            return simplejson.loads(obj, use_decimal=True,
                                    object_pairs_hook=jsonpatch.multidict)

>>> src = {}
>>> dst = {'bar': decimal.Decimal('1.10')}
>>> patch = DecimalJsonPatch.from_diff(src, dst)
>>> doc = {'foo': 1}
>>> result = patch.apply(doc)
{'foo': 1, 'bar': Decimal('1.10')}

Instead of subclassing it is also possible to pass a dump function to from_diff:

>>> patch = jsonpatch.JsonPatch.from_diff(src, dst, dumps=simplejson.dumps)

a dumps function to to_string:

>>> serialized_patch = patch.to_string(dumps=simplejson.dumps)
'[{"op": "add", "path": "/bar", "value": 1.10}]'

and load function to from_string:

>>> import functools
>>> loads = functools.partial(simplejson.loads, use_decimal=True,
                              object_pairs_hook=jsonpatch.multidict)
>>> patch.from_string(serialized_patch, loads=loads)
>>> doc = {'foo': 1}
>>> result = patch.apply(doc)
{'foo': 1, 'bar': Decimal('1.10')}