summaryrefslogtreecommitdiff
path: root/jsonpatch.py
diff options
context:
space:
mode:
authorArtyom Nikitin <a.nikitin@edadeal.ru>2020-11-23 12:51:18 +0300
committerArtyom Nikitin <a.nikitin@edadeal.ru>2020-11-23 12:51:18 +0300
commiteca4f8ab337b8ca8e9db5d0d0d81f536d77fbd7d (patch)
tree21d584d7d59b6cd4a917417b1f5a022e2d0cfe1a /jsonpatch.py
parent50fb942e3500d84950ec9309f886f1952bd2fa25 (diff)
parent24b5e86dd66824dce232ea07e95d39a67b1dd735 (diff)
downloadpython-json-patch-eca4f8ab337b8ca8e9db5d0d0d81f536d77fbd7d.tar.gz
Merge branch 'master' into feature/custom-pointer
# Conflicts: # jsonpatch.py # tests.py
Diffstat (limited to 'jsonpatch.py')
-rw-r--r--jsonpatch.py44
1 files changed, 34 insertions, 10 deletions
diff --git a/jsonpatch.py b/jsonpatch.py
index 92857ef..5522d50 100644
--- a/jsonpatch.py
+++ b/jsonpatch.py
@@ -171,6 +171,9 @@ def make_patch(src, dst, pointer_cls=JsonPointer):
class JsonPatch(object):
+ json_dumper = staticmethod(json.dumps)
+ json_loader = staticmethod(_jsonloads)
+
"""A JSON Patch is a list of Patch Operations.
>>> patch = JsonPatch([
@@ -229,6 +232,13 @@ class JsonPatch(object):
'copy': CopyOperation,
}
+ # Verify that the structure of the patch document
+ # is correct by retrieving each patch element.
+ # Much of the validation is done in the initializer
+ # though some is delayed until the patch is applied.
+ for op in self.patch:
+ self._get_operation(op)
+
def __str__(self):
"""str(self) -> self.to_string()"""
return self.to_string()
@@ -253,22 +263,30 @@ class JsonPatch(object):
return not(self == other)
@classmethod
- def from_string(cls, patch_str, pointer_cls=JsonPointer):
+ def from_string(cls, patch_str, loads=None, pointer_cls=JsonPointer):
"""Creates JsonPatch instance from string source.
:param patch_str: JSON patch as raw string.
- :type pointer_cls: str
+ :type patch_str: str
+
+ :param loads: A function of one argument that loads a serialized
+ JSON string.
+ :type loads: function
:param pointer_cls: JSON pointer class to use.
:type pointer_cls: Type[JsonPointer]
:return: :class:`JsonPatch` instance.
"""
- patch = _jsonloads(patch_str)
+ json_loader = loads or cls.json_loader
+ patch = json_loader(patch_str)
return cls(patch, pointer_cls=pointer_cls)
@classmethod
- def from_diff(cls, src, dst, optimization=True, pointer_cls=JsonPointer):
+ def from_diff(
+ cls, src, dst, optimization=True, dumps=None,
+ pointer_cls=JsonPointer,
+ ):
"""Creates JsonPatch instance based on comparison of two document
objects. Json patch would be created for `src` argument against `dst`
one.
@@ -279,6 +297,10 @@ class JsonPatch(object):
:param dst: Data source document object.
:type dst: dict
+ :param dumps: A function of one argument that produces a serialized
+ JSON string.
+ :type dumps: function
+
:param pointer_cls: JSON pointer class to use.
:type pointer_cls: Type[JsonPointer]
@@ -291,15 +313,16 @@ class JsonPatch(object):
>>> new == dst
True
"""
-
- builder = DiffBuilder(pointer_cls=pointer_cls)
+ json_dumper = dumps or cls.json_dumper
+ builder = DiffBuilder(json_dumper, pointer_cls=pointer_cls)
builder._compare_values('', None, src, dst)
ops = list(builder.execute())
return cls(ops, pointer_cls=pointer_cls)
- def to_string(self):
+ def to_string(self, dumps=None):
"""Returns patch set as JSON string."""
- return json.dumps(self.patch)
+ json_dumper = dumps or self.json_dumper
+ return json_dumper(self.patch)
@property
def _ops(self):
@@ -660,7 +683,8 @@ class CopyOperation(PatchOperation):
class DiffBuilder(object):
- def __init__(self, pointer_cls=JsonPointer):
+ def __init__(self, dumps=json.dumps, pointer_cls=JsonPointer):
+ self.dumps = dumps
self.pointer_cls = pointer_cls
self.index_storage = [{}, {}]
self.index_storage2 = [[], []]
@@ -856,7 +880,7 @@ class DiffBuilder(object):
# and ignore those that don't. The performance of this could be
# improved by doing more direct type checks, but we'd need to be
# careful to accept type changes that don't matter when JSONified.
- elif json.dumps(src) == json.dumps(dst):
+ elif self.dumps(src) == self.dumps(dst):
return
else: