Repository: stefankoegl/python-json-patch

Issue:
take_index causing 'move' of incorrect values due to bad True==1 comparison
See test here that reproduces the issue in code:
https://gist.github.com/Penguin2600/bca88971424a13f45d3560acf0e60f45

Or simply look at this REPL output  to understand the impact:
Taken from  line 714 of jsonpatch.py:

```
(Pdb) self.index_storage[st].keys()  
dict_keys([0.0, 1.0, 10.7, 'yes'])
(Pdb) stored = self.index_storage[st].get(True) 
(Pdb) len(stored)
1
```

In plain English, if my source data has a 1 or 1.0 anywhere and my destination data has a True anywhere jsonpatch will want to move 1.0 into the JSON where a true should be. This causes validation failures and in general incorrect output as in JSON '1.0' and 'true' are not the same thing.


Discussion:

Patch:
diff --git a/jsonpatch.py b/jsonpatch.py
index 429d40b..bd7701b 100644
--- a/jsonpatch.py
+++ b/jsonpatch.py
@@ -699,27 +699,29 @@ class DiffBuilder(object):
         root[:] = [root, root, None]
 
     def store_index(self, value, index, st):
+        typed_key = (value, type(value))
         try:
             storage = self.index_storage[st]
-            stored = storage.get(value)
+            stored = storage.get(typed_key)
             if stored is None:
-                storage[value] = [index]
+                storage[typed_key] = [index]
             else:
-                storage[value].append(index)
+                storage[typed_key].append(index)
 
         except TypeError:
-            self.index_storage2[st].append((value, index))
+            self.index_storage2[st].append((typed_key, index))
 
     def take_index(self, value, st):
+        typed_key = (value, type(value))
         try:
-            stored = self.index_storage[st].get(value)
+            stored = self.index_storage[st].get(typed_key)
             if stored:
                 return stored.pop()
 
         except TypeError:
             storage = self.index_storage2[st]
             for i in range(len(storage)-1, -1, -1):
-                if storage[i][0] == value:
+                if storage[i][0] == typed_key:
                     return storage.pop(i)[1]
 
     def insert(self, op):


Test patch:
diff --git a/tests.py b/tests.py
index a56ffc0..8a638cf 100755
--- a/tests.py
+++ b/tests.py
@@ -481,6 +481,15 @@ class MakePatchTestCase(unittest.TestCase):
         self.assertEqual(res, dst)
         self.assertIsInstance(res['A'], bool)
 
+    def test_issue129(self):
+        """In JSON 1 is different from True even though in python 1 == True Take Two"""
+        src = {'A': {'D': 1.0}, 'B': {'E': 'a'}}
+        dst = {'A': {'C': 'a'}, 'B': {'C': True}}
+        patch = jsonpatch.make_patch(src, dst)
+        res = jsonpatch.apply_patch(src, patch)
+        self.assertEqual(res, dst)
+        self.assertIsInstance(res['B']['C'], bool)
+
     def test_issue103(self):
         """In JSON 1 is different from 1.0 even though in python 1 == 1.0"""
         src = {'A': 1}