Repository: stefankoegl/python-json-patch

Issue:
Some case Failed when run ext_test
Hi @stefankoegl , when I run the external tests [json-patch-tests](https://github.com/json-patch/json-patch-tests), some case failed, I think some of them are bugs, others are due to unreasonable assertions.
here is the list:
- 1: pass only when changing **add** to **replace** -- **not sure if it is a bug**
```
    { "comment": "replace array document with object document?",
      "doc": [],
      "patch": [{"op": "add", "path": "", "value": {}}],
      "expected": {} }
```
- 2: failed with `KeyError: 'path'` before entering the assertion -- **unreasonable assertion**
```
    { "comment": "missing 'path' parameter",
      "doc": {},
      "patch": [ { "op": "add", "value": "bar" } ],
      "error": "missing 'path' parameter" }
```

- 3: failed with `TypeError: expected string or bytes-like object` before entering the assertion -- **unreasonable assertion**
```
      { "comment": "'path' parameter with null value",
        "doc": {},
        "patch": [ { "op": "add", "path": null, "value": "bar" } ],
        "error": "null is not valid value for 'path'" }
```

-4: index leading with zero should failed but success -- **bug**
```
      { "comment": "test with bad array number that has leading zeros",
        "doc": ["foo", "bar"],
        "patch": [{"op": "test", "path": "/00", "value": "foo"}],
        "error": "test op should reject the array value, it has leading zeros" },
  
      { "comment": "test with bad array number that has leading zeros",
        "doc": ["foo", "bar"],
        "patch": [{"op": "test", "path": "/01", "value": "bar"}],
        "error": "test op should reject the array value, it has leading zeros" }
```

Comments:

Patch:
diff --git a/jsonpatch.py b/jsonpatch.py
index ca22e34..7d5489a 100644
--- a/jsonpatch.py
+++ b/jsonpatch.py
@@ -334,12 +334,18 @@ class PatchOperation(object):
 
     def __init__(self, operation):
 
+        if not operation.__contains__('path'):
+            raise InvalidJsonPatch("Operation must have a 'path' member")
+
         if isinstance(operation['path'], JsonPointer):
             self.location = operation['path'].path
             self.pointer = operation['path']
         else:
             self.location = operation['path']
-            self.pointer = JsonPointer(self.location)
+            try:
+                self.pointer = JsonPointer(self.location)
+            except TypeError as ex:
+                raise InvalidJsonPatch("Invalid 'path'")
 
         self.operation = operation
 
@@ -473,6 +479,9 @@ class ReplaceOperation(PatchOperation):
         if part is None:
             return value
 
+        if part == "-":
+            raise InvalidJsonPatch("'path' with '-' can't be applied to 'replace' operation")
+
         if isinstance(subobj, MutableSequence):
             if part >= len(subobj) or part < 0:
                 raise JsonPatchConflict("can't replace outside of list")


Test patch:
diff --git a/tests.py b/tests.py
index cde90b0..0abf4d2 100755
--- a/tests.py
+++ b/tests.py
@@ -219,6 +219,17 @@ class ApplyPatchTestCase(unittest.TestCase):
             ])
         self.assertEqual(res['foo'], [1, 2, 3, 4])
 
+    def test_add_missing_path(self):
+        obj = {'bar': 'qux'}
+        self.assertRaises(jsonpatch.InvalidJsonPatch,
+                          jsonpatch.apply_patch,
+                          obj, [{'op': 'test', 'value': 'bar'}])
+
+    def test_path_with_null_value(self):
+        obj = {'bar': 'qux'}
+        self.assertRaises(jsonpatch.InvalidJsonPatch,
+                          jsonpatch.apply_patch,
+                          obj, '[{"op": "add", "path": null, "value": "bar"}]')
 
 
 class EqualityTestCase(unittest.TestCase):