diff options
author | Alexander Shorin <kxepal@gmail.com> | 2012-07-15 23:37:38 +0400 |
---|---|---|
committer | Alexander Shorin <kxepal@gmail.com> | 2012-07-15 23:37:38 +0400 |
commit | 76bc4422c190606b7c7b8ad8cb22cdf2e85ac433 (patch) | |
tree | 52ffb88a401c9d553a2843273346a0fefdf86164 | |
parent | 564e39be424f8151a2749055e06d0b5b4666bbf0 (diff) | |
download | python-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.py | 27 |
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))) |