diff --git a/src/json.hpp b/src/json.hpp index 421b9995..acde03bf 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -9525,6 +9525,7 @@ basic_json_parser_63: const auto it_op = val.m_value.object->find("op"); const auto it_path = val.m_value.object->find("path"); const auto it_value = val.m_value.object->find("value"); + const auto it_from = val.m_value.object->find("from"); if (it_op == val.m_value.object->end() or not it_op->second.is_string()) { @@ -9558,12 +9559,30 @@ basic_json_parser_63: { throw std::domain_error("'replace' operation must have member 'value'"); } + + result.at(ptr) = it_value->second; } else if (op == "move") { + if (it_from == val.m_value.object->end()) + { + throw std::domain_error("'move' operation must have member 'from'"); + } + + const std::string from_path = it_from->second; + const json_pointer from_ptr(from_path); } else if (op == "copy") { + if (it_from == val.m_value.object->end()) + { + throw std::domain_error("'copy' operation must have member 'from'"); + } + + const std::string from_path = it_from->second; + const json_pointer from_ptr(from_path); + + result[ptr] = result.at(from_ptr); } else if (op == "test") { diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 3f839737..d161f38d 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8835,6 +8835,7 @@ class basic_json const auto it_op = val.m_value.object->find("op"); const auto it_path = val.m_value.object->find("path"); const auto it_value = val.m_value.object->find("value"); + const auto it_from = val.m_value.object->find("from"); if (it_op == val.m_value.object->end() or not it_op->second.is_string()) { @@ -8868,12 +8869,30 @@ class basic_json { throw std::domain_error("'replace' operation must have member 'value'"); } + + result.at(ptr) = it_value->second; } else if (op == "move") { + if (it_from == val.m_value.object->end()) + { + throw std::domain_error("'move' operation must have member 'from'"); + } + + const std::string from_path = it_from->second; + const json_pointer from_ptr(from_path); } else if (op == "copy") { + if (it_from == val.m_value.object->end()) + { + throw std::domain_error("'copy' operation must have member 'from'"); + } + + const std::string from_path = it_from->second; + const json_pointer from_ptr(from_path); + + result[ptr] = result.at(from_ptr); } else if (op == "test") { diff --git a/test/unit.cpp b/test/unit.cpp index 7a91efd7..7b675462 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -12421,6 +12421,34 @@ TEST_CASE("JSON patch") CHECK(doc.apply_patch(patch) == expected); } + SECTION("example A.5 - Replacing a Value") + { + // An example target JSON document: + json doc = R"( + { + "baz": "qux", + "foo": "bar" + } + )"_json; + + // A JSON Patch document: + json patch = R"( + [ + { "op": "replace", "path": "/baz", "value": "boo" } + ] + )"_json; + + json expected = R"( + { + "baz": "boo", + "foo": "bar" + } + )"_json; + + // check if patched value is as expected + CHECK(doc.apply_patch(patch) == expected); + } + SECTION("example A.8 - Testing a Value: Success") { // An example target JSON document: @@ -12615,6 +12643,48 @@ TEST_CASE("JSON patch") CHECK(doc.apply_patch(patch) == expected); } } + + SECTION("own examples") + { + SECTION("copy") + { + // An example target JSON document: + json doc = R"( + { + "foo": { + "bar": "baz", + "waldo": "fred" + }, + "qux": { + "corge": "grault" + } + } + )"_json; + + // A JSON Patch document: + json patch = R"( + [ + { "op": "copy", "from": "/foo/waldo", "path": "/qux/thud" } + ] + )"_json; + + json expected = R"( + { + "foo": { + "bar": "baz", + "waldo": "fred" + }, + "qux": { + "corge": "grault", + "thud": "fred" + } + } + )"_json; + + // check if patched value is as expected + CHECK(doc.apply_patch(patch) == expected); + } + } } TEST_CASE("regression tests")