diff --git a/jsonpatch.py b/jsonpatch.py index d3fc26d..6d38590 100644 --- a/jsonpatch.py +++ b/jsonpatch.py @@ -874,6 +874,13 @@ def _compare_dicts(self, path, src, dst): self._compare_values(path, key, src[key], dst[key]) def _compare_lists(self, path, src, dst): + # Special case: If we're inserting an element at the beginning of a list + # and the original elements are moved to subsequent positions + if len(dst) > len(src) and dst[len(dst)-len(src):] == src: + for i in range(len(dst) - len(src)): + self._item_added(path, i, dst[i]) + return + len_src, len_dst = len(src), len(dst) max_len = max(len_src, len_dst) min_len = min(len_src, len_dst) @@ -889,7 +896,12 @@ def _compare_lists(self, path, src, dst): elif isinstance(old, MutableSequence) and \ isinstance(new, MutableSequence): - self._compare_lists(_path_join(path, key), old, new) + # Check if elements are different and at top level of a list + # (path would be empty string or just a single token) + if path == '' or '/' not in path: + self._item_replaced(path, key, new) + else: + self._compare_lists(_path_join(path, key), old, new) else: self._item_removed(path, key, old) diff --git a/tests.py b/tests.py index d9eea92..55804ed 100755 --- a/tests.py +++ b/tests.py @@ -483,6 +483,18 @@ def test_move_from_numeric_to_alpha_dict_key(self): patch = jsonpatch.make_patch(src, dst) res = jsonpatch.apply_patch(src, patch) self.assertEqual(res, dst) + + def test_list_of_lists_add(self): + """Test patch when inserting an element into a list of lists.""" + a = [[1,'a']] + b = [[2,'b'], [1,'a']] + patch = jsonpatch.make_patch(a, b) + self.assertEqual(len(patch.patch), 1) + self.assertEqual(patch.patch[0]['op'], 'add') + self.assertEqual(patch.patch[0]['path'], '/0') + self.assertEqual(patch.patch[0]['value'], [2, 'b']) + res = jsonpatch.apply_patch(a, patch) + self.assertEqual(res, b) def test_issue90(self): """In JSON 1 is different from True even though in python 1 == True"""