summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Shorin <kxepal@gmail.com>2012-07-15 23:37:38 +0400
committerAlexander Shorin <kxepal@gmail.com>2012-07-15 23:37:38 +0400
commit76bc4422c190606b7c7b8ad8cb22cdf2e85ac433 (patch)
tree52ffb88a401c9d553a2843273346a0fefdf86164
parent564e39be424f8151a2749055e06d0b5b4666bbf0 (diff)
downloadpython-json-patch-76bc4422c190606b7c7b8ad8cb22cdf2e85ac433.tar.gz
Fix issue #4.
Patch creation from diff of two JSON documents was able to produce invalid instance if there was need to add more than 1 array element. In this situation, elements been tryed be added since higher index that is far outside of target. That's correct order if we removing array elements (from higher index to lower one), but we should add elements in reversed order (from lower index to higher).
-rw-r--r--jsonpatch.py27
1 files changed, 15 insertions, 12 deletions
diff --git a/jsonpatch.py b/jsonpatch.py
index 1240586..b0c2faa 100644
--- a/jsonpatch.py
+++ b/jsonpatch.py
@@ -218,6 +218,8 @@ class JsonPatch(object):
True
"""
def compare_values(path, value, other):
+ if value == other:
+ return
if isinstance(value, dict) and isinstance(other, dict):
for operation in compare_dict(path, value, other):
yield operation
@@ -231,25 +233,26 @@ class JsonPatch(object):
for key in src:
if key not in dst:
yield {'remove': '/'.join(path + [key])}
- elif src[key] != dst[key]:
- current = path + [key]
- for operation in compare_values(current, src[key], dst[key]):
- yield operation
+ continue
+ current = path + [key]
+ for operation in compare_values(current, src[key], dst[key]):
+ yield operation
for key in dst:
if key not in src:
yield {'add': '/'.join(path + [key]), 'value': dst[key]}
def compare_list(path, src, dst):
lsrc, ldst = len(src), len(dst)
- for idx in reversed(range(max(lsrc, ldst))):
- if idx < lsrc and idx < ldst:
+ for idx in range(min(lsrc, ldst)):
+ current = path + [str(idx)]
+ for operation in compare_values(current, src[idx], dst[idx]):
+ yield operation
+ if lsrc < ldst:
+ for idx in range(lsrc, ldst):
current = path + [str(idx)]
- for operation in compare_values(current, src[idx], dst[idx]):
- yield operation
- elif idx < ldst:
- yield {'add': '/'.join(path + [str(idx)]),
- 'value': dst[idx]}
- elif idx < lsrc:
+ yield {'add': '/'.join(current), 'value': dst[idx]}
+ elif lsrc > ldst:
+ for idx in reversed(range(ldst, lsrc)):
yield {'remove': '/'.join(path + [str(idx)])}
return cls(list(compare_dict([''], src, dst)))