Testing using file json_patch_spec_tests.json Testing '4.1. add with missing object', doc '{ "q": { "bar": 2 } }' patch '[ { "op": "add", "path": "\/a\/b", "value": 1 } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Failed to set value at path referenced by 'path' field Testing 'A.1. Adding an Object Member', doc '{ "foo": "bar" }' patch '[ { "op": "add", "path": "\/baz", "value": "qux" } ]' : OK Testing 'A.2. Adding an Array Element', doc '{ "foo": [ "bar", "baz" ] }' patch '[ { "op": "add", "path": "\/foo\/1", "value": "qux" } ]' : OK Testing 'A.3. Removing an Object Member', doc '{ "baz": "qux", "foo": "bar" }' patch '[ { "op": "remove", "path": "\/baz" } ]' : OK Testing 'A.4. Removing an Array Element', doc '{ "foo": [ "bar", "qux", "baz" ] }' patch '[ { "op": "remove", "path": "\/foo\/1" } ]' : OK Testing 'A.5. Replacing a Value', doc '{ "baz": "qux", "foo": "bar" }' patch '[ { "op": "replace", "path": "\/baz", "value": "boo" } ]' : OK Testing 'A.6. Moving a Value', doc '{ "foo": { "bar": "baz", "waldo": "fred" }, "qux": { "corge": "grault" } }' patch '[ { "op": "move", "from": "\/foo\/waldo", "path": "\/qux\/thud" } ]' : OK Testing 'A.7. Moving an Array Element', doc '{ "foo": [ "all", "grass", "cows", "eat" ] }' patch '[ { "op": "move", "from": "\/foo\/1", "path": "\/foo\/3" } ]' : OK Testing 'A.8. Testing a Value: Success', doc '{ "baz": "qux", "foo": [ "a", 2, "c" ] }' patch '[ { "op": "test", "path": "\/baz", "value": "qux" }, { "op": "test", "path": "\/foo\/1", "value": 2 } ]' : OK Testing 'A.9. Testing a Value: Error', doc '{ "baz": "qux" }' patch '[ { "op": "test", "path": "\/baz", "value": "bar" } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Value of element referenced by 'path' field did not match 'value' field Testing 'A.10. Adding a nested Member Object', doc '{ "foo": "bar" }' patch '[ { "op": "add", "path": "\/child", "value": { "grandchild": { } } } ]' : OK Testing 'A.11. Ignoring Unrecognized Elements', doc '{ "foo": "bar" }' patch '[ { "op": "add", "path": "\/baz", "value": "qux", "xyz": 123 } ]' : OK Testing 'A.12. Adding to a Non-existent Target', doc '{ "foo": "bar" }' patch '[ { "op": "add", "path": "\/baz\/bat", "value": "qux" } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Failed to set value at path referenced by 'path' field Testing 'A.13 Invalid JSON Patch Document', doc '{ "foo": "bar" }' patch '[ { "op": "remove", "path": "\/baz", "value": "qux" } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Did not find element referenced by path field Testing 'A.14. ~ Escape Ordering', doc '{ "\/": 9, "~1": 10 }' patch '[ { "op": "test", "path": "\/~01", "value": 10 } ]' : OK Testing 'A.15. Comparing Strings and Numbers', doc '{ "\/": 9, "~1": 10 }' patch '[ { "op": "test", "path": "\/~01", "value": "10" } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Value of element referenced by 'path' field did not match 'value' field Testing 'A.16. Adding an Array Value', doc '{ "foo": [ "bar" ] }' patch '[ { "op": "add", "path": "\/foo\/-", "value": [ "abc", "def" ] } ]' : OK Testing using file json_patch_tests.json Testing 'empty list, empty docs', doc '{ }' patch '[ ]' : OK Testing 'empty patch list', doc '{ "foo": 1 }' patch '[ ]' : OK Testing 'rearrangements OK?', doc '{ "foo": 1, "bar": 2 }' patch '[ ]' : OK Testing 'rearrangements OK? How about one level down ... array', doc '[ { "foo": 1, "bar": 2 } ]' patch '[ ]' : OK Testing 'rearrangements OK? How about one level down...', doc '{ "foo": { "foo": 1, "bar": 2 } }' patch '[ ]' : OK Testing 'add replaces any existing field', doc '{ "foo": null }' patch '[ { "op": "add", "path": "\/foo", "value": 1 } ]' : OK Testing 'toplevel array', doc '[ ]' patch '[ { "op": "add", "path": "\/0", "value": "foo" } ]' : OK Testing 'toplevel array, no change', doc '[ "foo" ]' patch '[ ]' : OK Testing 'toplevel object, numeric string', doc '{ }' patch '[ { "op": "add", "path": "\/foo", "value": "1" } ]' : OK Testing 'toplevel object, integer', doc '{ }' patch '[ { "op": "add", "path": "\/foo", "value": 1 } ]' : OK Testing 'Toplevel scalar values OK?', doc 'foo' patch '[ { "op": "replace", "path": "", "value": "bar" } ]' : OK Testing 'replace object document with array document?', doc '{ }' patch '[ { "op": "add", "path": "", "value": [ ] } ]' : OK Testing 'replace array document with object document?', doc '[ ]' patch '[ { "op": "add", "path": "", "value": { } } ]' : OK Testing 'append to root array document?', doc '[ ]' patch '[ { "op": "add", "path": "\/-", "value": "hi" } ]' : OK Testing 'Add, / target', doc '{ }' patch '[ { "op": "add", "path": "\/", "value": 1 } ]' : OK Testing 'Add, /foo/ deep target (trailing slash)', doc '{ "foo": { } }' patch '[ { "op": "add", "path": "\/foo\/", "value": 1 } ]' : OK Testing 'Add composite value at top level', doc '{ "foo": 1 }' patch '[ { "op": "add", "path": "\/bar", "value": [ 1, 2 ] } ]' : OK Testing 'Add into composite value', doc '{ "foo": 1, "baz": [ { "qux": "hello" } ] }' patch '[ { "op": "add", "path": "\/baz\/0\/foo", "value": "world" } ]' : OK Testing 'Out of bounds (upper)', doc '{ "bar": [ 1, 2 ] }' patch '[ { "op": "add", "path": "\/bar\/8", "value": "5" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Failed to set value at path referenced by 'path' field Testing 'Out of bounds (lower)', doc '{ "bar": [ 1, 2 ] }' patch '[ { "op": "add", "path": "\/bar\/-1", "value": "5" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Failed to set value at path referenced by 'path' field Testing '(null)', doc '{ "foo": 1 }' patch '[ { "op": "add", "path": "\/bar", "value": true } ]' : OK Testing '(null)', doc '{ "foo": 1 }' patch '[ { "op": "add", "path": "\/bar", "value": false } ]' : OK Testing '(null)', doc '{ "foo": 1 }' patch '[ { "op": "add", "path": "\/bar", "value": null } ]' : OK Testing '0 can be an array index or object element name', doc '{ "foo": 1 }' patch '[ { "op": "add", "path": "\/0", "value": "bar" } ]' : OK Testing '(null)', doc '[ "foo" ]' patch '[ { "op": "add", "path": "\/1", "value": "bar" } ]' : OK Testing '(null)', doc '[ "foo", "sil" ]' patch '[ { "op": "add", "path": "\/1", "value": "bar" } ]' : OK Testing '(null)', doc '[ "foo", "sil" ]' patch '[ { "op": "add", "path": "\/0", "value": "bar" } ]' : OK Testing 'push item to array via last index + 1', doc '[ "foo", "sil" ]' patch '[ { "op": "add", "path": "\/2", "value": "bar" } ]' : OK Testing 'add item to array at index > length should fail', doc '[ "foo", "sil" ]' patch '[ { "op": "add", "path": "\/3", "value": "bar" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Failed to set value at path referenced by 'path' field Testing 'test against implementation-specific numeric parsing', doc '{ "1e0": "foo" }' patch '[ { "op": "test", "path": "\/1e0", "value": "foo" } ]' : OK Testing 'test with bad number should fail', doc '[ "foo", "bar" ]' patch '[ { "op": "test", "path": "\/1e0", "value": "bar" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Invalid path field Testing 'Object operation on array target', doc '[ "foo", "sil" ]' patch '[ { "op": "add", "path": "\/bar", "value": 42 } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Failed to set value at path referenced by 'path' field Testing 'value in array add not flattened', doc '[ "foo", "sil" ]' patch '[ { "op": "add", "path": "\/1", "value": [ "bar", "baz" ] } ]' : OK Testing '(null)', doc '{ "foo": 1, "bar": [ 1, 2, 3, 4 ] }' patch '[ { "op": "remove", "path": "\/bar" } ]' : OK Testing '(null)', doc '{ "foo": 1, "baz": [ { "qux": "hello" } ] }' patch '[ { "op": "remove", "path": "\/baz\/0\/qux" } ]' : OK Testing '(null)', doc '{ "foo": 1, "baz": [ { "qux": "hello" } ] }' patch '[ { "op": "replace", "path": "\/foo", "value": [ 1, 2, 3, 4 ] } ]' : OK Testing '(null)', doc '{ "foo": [ 1, 2, 3, 4 ], "baz": [ { "qux": "hello" } ] }' patch '[ { "op": "replace", "path": "\/baz\/0\/qux", "value": "world" } ]' : OK Testing '(null)', doc '[ "foo" ]' patch '[ { "op": "replace", "path": "\/0", "value": "bar" } ]' : OK Testing '(null)', doc '[ "" ]' patch '[ { "op": "replace", "path": "\/0", "value": 0 } ]' : OK Testing '(null)', doc '[ "" ]' patch '[ { "op": "replace", "path": "\/0", "value": true } ]' : OK Testing '(null)', doc '[ "" ]' patch '[ { "op": "replace", "path": "\/0", "value": false } ]' : OK Testing '(null)', doc '[ "" ]' patch '[ { "op": "replace", "path": "\/0", "value": null } ]' : OK Testing 'value in array replace not flattened', doc '[ "foo", "sil" ]' patch '[ { "op": "replace", "path": "\/1", "value": [ "bar", "baz" ] } ]' : OK Testing 'replace whole document', doc '{ "foo": "bar" }' patch '[ { "op": "replace", "path": "", "value": { "baz": "qux" } } ]' : OK Testing 'add whole document, null', doc '{ }' patch '[ { "op": "remove", "path": "" }, { "op": "add", "path": "", "value": { "baz": "qux" } } ]' : OK Testing 'replace whole document, null', doc '{ }' patch '[ { "op": "remove", "path": "" }, { "op": "replace", "path": "", "value": { "baz": "qux" } } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 1: Invalid path field Testing 'remove whole document', doc '{ "foo": "bar" }' patch '[ { "op": "remove", "path": "" } ]' : OK Testing 'remove whole document', doc '{ "foo": "bar" }' patch '[ { "op": "remove", "path": "" } ]' : OK Testing 'remove whole document, array', doc '[ "foo", "bar" ]' patch '[ { "op": "remove", "path": "" } ]' : OK Testing 'remove whole document, string', doc 'foo' patch '[ { "op": "remove", "path": "" } ]' : OK Testing 'remove whole document, null', doc '{ }' patch '[ { "op": "remove", "path": "" }, { "op": "remove", "path": "" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 1: Invalid path field Testing 'test replace with missing parent key should fail', doc '{ "bar": "baz" }' patch '[ { "op": "replace", "path": "\/foo\/bar", "value": false } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Did not find element referenced by path field Testing 'spurious patch properties', doc '{ "foo": 1 }' patch '[ { "op": "test", "path": "\/foo", "value": 1, "spurious": 1 } ]' : OK Testing 'null value should be valid obj property', doc '{ "foo": null }' patch '[ { "op": "test", "path": "\/foo", "value": null } ]' : OK Testing 'null value should be valid obj property to be replaced with something truthy', doc '{ "foo": null }' patch '[ { "op": "replace", "path": "\/foo", "value": "truthy" } ]' : OK Testing 'null value should be valid obj property to be moved', doc '{ "foo": null }' patch '[ { "op": "move", "from": "\/foo", "path": "\/bar" } ]' : OK Testing 'null value should be valid obj property to be copied', doc '{ "foo": null }' patch '[ { "op": "copy", "from": "\/foo", "path": "\/bar" } ]' : OK Testing 'null value should be valid obj property to be removed', doc '{ "foo": null }' patch '[ { "op": "remove", "path": "\/foo" } ]' : OK Testing 'null value should still be valid obj property replace other value', doc '{ "foo": "bar" }' patch '[ { "op": "replace", "path": "\/foo", "value": null } ]' : OK Testing 'test should pass despite rearrangement', doc '{ "foo": { "foo": 1, "bar": 2 } }' patch '[ { "op": "test", "path": "\/foo", "value": { "bar": 2, "foo": 1 } } ]' : OK Testing 'test should pass despite (nested) rearrangement', doc '{ "foo": [ { "foo": 1, "bar": 2 } ] }' patch '[ { "op": "test", "path": "\/foo", "value": [ { "bar": 2, "foo": 1 } ] } ]' : OK Testing 'test should pass - no error', doc '{ "foo": { "bar": [ 1, 2, 5, 4 ] } }' patch '[ { "op": "test", "path": "\/foo", "value": { "bar": [ 1, 2, 5, 4 ] } } ]' : OK Testing 'test op should fail', doc '{ "foo": { "bar": [ 1, 2, 5, 4 ] } }' patch '[ { "op": "test", "path": "\/foo", "value": [ 1, 2 ] } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Value of element referenced by 'path' field did not match 'value' field Testing 'Test the whole document', doc '{ "foo": 1 }' patch '[ { "op": "test", "path": "", "value": { "foo": 1 } } ]' : OK Testing 'Test the whole document, no match', doc '{ "foo": 1 }' patch '[ { "op": "test", "path": "", "value": { "foo": 2 } } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Value of element referenced by 'path' field did not match 'value' field Testing 'Empty-string element', doc '{ "": 1 }' patch '[ { "op": "test", "path": "\/", "value": 1 } ]' : OK Testing '(null)', doc '{ "foo": [ "bar", "baz" ], "": 0, "a\/b": 1, "c%d": 2, "e^f": 3, "g|h": 4, "i\\j": 5, "k\"l": 6, " ": 7, "m~n": 8 }' patch '[ { "op": "test", "path": "\/foo", "value": [ "bar", "baz" ] }, { "op": "test", "path": "\/foo\/0", "value": "bar" }, { "op": "test", "path": "\/", "value": 0 }, { "op": "test", "path": "\/a~1b", "value": 1 }, { "op": "test", "path": "\/c%d", "value": 2 }, { "op": "test", "path": "\/e^f", "value": 3 }, { "op": "test", "path": "\/g|h", "value": 4 }, { "op": "test", "path": "\/i\\j", "value": 5 }, { "op": "test", "path": "\/k\"l", "value": 6 }, { "op": "test", "path": "\/ ", "value": 7 }, { "op": "test", "path": "\/m~0n", "value": 8 } ]' : OK Testing 'Move to same location has no effect', doc '{ "foo": 1 }' patch '[ { "op": "move", "from": "\/foo", "path": "\/foo" } ]' : OK Testing '(null)', doc '{ "foo": 1, "baz": [ { "qux": "hello" } ] }' patch '[ { "op": "move", "from": "\/foo", "path": "\/bar" } ]' : OK Testing '(null)', doc '{ "baz": [ { "qux": "hello" } ], "bar": 1 }' patch '[ { "op": "move", "from": "\/baz\/0\/qux", "path": "\/baz\/1" } ]' : OK Testing '(null)', doc '{ "baz": [ { "qux": "hello" } ], "bar": 1 }' patch '[ { "op": "copy", "from": "\/baz\/0", "path": "\/boo" } ]' : OK Testing 'replacing the root of the document is possible with add', doc '{ "foo": "bar" }' patch '[ { "op": "add", "path": "", "value": { "baz": "qux" } } ]' : OK Testing 'Adding to "/-" adds to the end of the array', doc '[ 1, 2 ]' patch '[ { "op": "add", "path": "\/-", "value": { "foo": [ "bar", "baz" ] } } ]' : OK Testing 'Adding to "/-" adds to the end of the array, even n levels down', doc '[ 1, 2, [ 3, [ 4, 5 ] ] ]' patch '[ { "op": "add", "path": "\/2\/1\/-", "value": { "foo": [ "bar", "baz" ] } } ]' : OK Testing 'test remove with bad number should fail', doc '{ "foo": 1, "baz": [ { "qux": "hello" } ] }' patch '[ { "op": "remove", "path": "\/baz\/1e0\/qux" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Invalid path field Testing 'test remove on array', doc '[ 1, 2, 3, 4 ]' patch '[ { "op": "remove", "path": "\/0" } ]' : OK Testing 'test repeated removes', doc '[ 1, 2, 3, 4 ]' patch '[ { "op": "remove", "path": "\/1" }, { "op": "remove", "path": "\/2" } ]' : OK Testing 'test remove with bad index should fail', doc '[ 1, 2, 3, 4 ]' patch '[ { "op": "remove", "path": "\/1e0" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Invalid path field Testing 'test replace with bad number should fail', doc '[ "" ]' patch '[ { "op": "replace", "path": "\/1e0", "value": false } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Invalid path field Testing 'test copy with bad number should fail', doc '{ "baz": [ 1, 2, 3 ], "bar": 1 }' patch '[ { "op": "copy", "from": "\/baz\/1e0", "path": "\/boo" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Invalid from field Testing 'test move with bad number should fail', doc '{ "foo": 1, "baz": [ 1, 2, 3, 4 ] }' patch '[ { "op": "move", "from": "\/baz\/1e0", "path": "\/foo" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Invalid from field Testing 'test add with bad number should fail', doc '[ "foo", "sil" ]' patch '[ { "op": "add", "path": "\/1e0", "value": "bar" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Failed to set value at path referenced by 'path' field Testing 'missing 'path' parameter', doc '{ }' patch '[ { "op": "add", "value": "bar" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Patch object does not contain 'path' field Testing ''path' parameter with null value', doc '{ }' patch '[ { "op": "add", "path": null, "value": "bar" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Failed to set value at path referenced by 'path' field Testing 'invalid JSON Pointer token', doc '{ }' patch '[ { "op": "add", "path": "foo", "value": "bar" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Failed to set value at path referenced by 'path' field Testing 'missing 'value' parameter to add', doc '[ 1 ]' patch '[ { "op": "add", "path": "\/-" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Patch object does not contain a 'value' field Testing 'missing 'value' parameter to replace', doc '[ 1 ]' patch '[ { "op": "replace", "path": "\/0" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Patch object does not contain a 'value' field Testing 'missing 'value' parameter to test', doc '[ null ]' patch '[ { "op": "test", "path": "\/0" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Patch object does not contain a 'value' field Testing 'missing value parameter to test - where undef is falsy', doc '[ false ]' patch '[ { "op": "test", "path": "\/0" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Patch object does not contain a 'value' field Testing 'missing from parameter to copy', doc '[ 1 ]' patch '[ { "op": "copy", "path": "\/-" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Patch does not contain a 'from' field Testing 'missing from location to copy', doc '{ "foo": 1 }' patch '[ { "op": "copy", "from": "\/bar", "path": "\/foo" } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Did not find element referenced by from field Testing 'missing from parameter to move', doc '{ "foo": 1 }' patch '[ { "op": "move", "path": "" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Patch does not contain a 'from' field Testing 'missing from location to move', doc '{ "foo": 1 }' patch '[ { "op": "move", "from": "\/bar", "path": "\/foo" } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Did not find element referenced by from field Testing 'duplicate ops, json-c parses this as op:move', doc '{ "foo": "bar" }' patch '[ { "op": "move", "path": "\/baz", "value": "qux", "from": "\/foo" } ]' : OK Testing 'unrecognized op should fail', doc '{ "foo": 1 }' patch '[ { "op": "spam", "path": "\/foo", "value": 1 } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Patch object has invalid 'op' field Testing 'test with bad array number that has leading zeros', doc '[ "foo", "bar" ]' patch '[ { "op": "test", "path": "\/00", "value": "foo" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Invalid path field Testing 'test with bad array number that has leading zeros', doc '[ "foo", "bar" ]' patch '[ { "op": "test", "path": "\/01", "value": "bar" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Invalid path field Testing 'Removing nonexistent field', doc '{ "foo": "bar" }' patch '[ { "op": "remove", "path": "\/baz" } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Did not find element referenced by path field Testing 'Removing deep nonexistent path', doc '{ "foo": "bar" }' patch '[ { "op": "remove", "path": "\/missing1\/missing2" } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Did not find element referenced by path field Testing 'Removing nonexistent index', doc '[ "foo", "bar" ]' patch '[ { "op": "remove", "path": "\/2" } ]' : OK => json_patch_apply failed as expected: ERRNO=ENOENT at patch idx 0: Did not find element referenced by path field Testing 'Patch with different capitalisation than doc', doc '{ "foo": "bar" }' patch '[ { "op": "add", "path": "\/FOO", "value": "BAR" } ]' : OK