From 7033ee42e295ef5129f55d9ca1696317434ff2e9 Mon Sep 17 00:00:00 2001 From: Daniel Parker Date: Thu, 16 Nov 2023 16:39:07 -0500 Subject: [PATCH] json_location erase --- .../jsoncons_ext/jsonpath/json_location.hpp | 48 ++++++- test/jsonpath/src/json_location_tests.cpp | 136 +++++++++++++++++- 2 files changed, 175 insertions(+), 9 deletions(-) diff --git a/include/jsoncons_ext/jsonpath/json_location.hpp b/include/jsoncons_ext/jsonpath/json_location.hpp index 61ff42c082..3797f76de9 100644 --- a/include/jsoncons_ext/jsonpath/json_location.hpp +++ b/include/jsoncons_ext/jsonpath/json_location.hpp @@ -222,24 +222,62 @@ namespace jsonpath { } }; - template - std::size_t remove(Json& instance, const basic_json_location& location) + std::size_t erase(Json& instance, const basic_json_location& location) { std::size_t count = 0; Json* p_current = std::addressof(instance); - for (const auto& element : location) + + std::size_t last = location.size() == 0 ? 0 : location.size() - 1; + for (std::size_t i = 0; i < location.size(); ++i) { + const auto& element = location[i]; if (element.has_name()) { if (p_current->is_object()) { - + auto it = p_current->find(element.name()); + if (it != p_current->object_range().end()) + { + if (i < last) + { + p_current = std::addressof(it->value()); + } + else + { + p_current->erase(it); + count = 1; + } + } + else + { + break; + } + } + else + { + break; } } - else + else // if (element.has_index()) { + if (p_current->is_array() && element.index() < p_current->size()) + { + if (i < last) + { + p_current = std::addressof(p_current->at(element.index())); + } + else + { + p_current->erase(p_current->array_range().begin()+element.index()); + count = 1; + } + } + else + { + break; + } } } return count; diff --git a/test/jsonpath/src/json_location_tests.cpp b/test/jsonpath/src/json_location_tests.cpp index 0e135f5226..c9498dfd1c 100644 --- a/test/jsonpath/src/json_location_tests.cpp +++ b/test/jsonpath/src/json_location_tests.cpp @@ -1,19 +1,19 @@ // Copyright 2013-2023 Daniel Parker // Distributed under Boost license -#include +#include #include #include using namespace jsoncons; -TEST_CASE("test json_location") +TEST_CASE("json_location tests") { + SECTION("test 1") { jsonpath::json_location loc; - loc /= "foo"; - loc /= 1; + loc.append("foo").append(1); CHECK(loc.size() == 2); CHECK(loc[0].has_name()); @@ -23,3 +23,131 @@ TEST_CASE("test json_location") } } + +TEST_CASE("json_location erase tests") +{ + + std::string json_string = R"( +{ "store": { + "book": [ + { "category": "reference", + "author": "Nigel Rees", + "title": "Sayings of the Century", + "price": 8.95 + }, + { "category": "fiction", + "author": "Evelyn Waugh", + "title": "Sword of Honour", + "price": 12.99 + }, + { "category": "fiction", + "author": "Herman Melville", + "title": "Moby Dick", + "isbn": "0-553-21311-3", + "price": 8.99 + } + ] + } +} + )"; + + json doc = json::parse(json_string); + + SECTION("store book 1") + { + jsonpath::json_location loc; + loc.append("store").append("book").append(1); + + + CHECK(doc["store"]["book"].size() == 3); + CHECK(doc["store"]["book"][1]["author"].as() == "Evelyn Waugh"); + + std::size_t count = jsonpath::erase(doc, loc); + + CHECK(count == 1); + CHECK(doc["store"]["book"].size() == 2); + CHECK(doc["store"]["book"][1]["author"].as() == "Herman Melville"); + } + + SECTION("store book 2") + { + jsonpath::json_location loc; + loc.append("store").append("book").append(2); + + + CHECK(doc["store"]["book"].size() == 3); + CHECK(doc["store"]["book"][2]["author"].as() == "Herman Melville"); + + std::size_t count = jsonpath::erase(doc, loc); + + CHECK(count == 1); + CHECK(doc["store"]["book"].size() == 2); + CHECK(doc["store"]["book"][1]["author"].as() == "Evelyn Waugh"); + } + + SECTION("store book 3") + { + jsonpath::json_location loc; + loc.append("store").append("book").append(3); + + CHECK(doc["store"]["book"].size() == 3); + CHECK(doc["store"]["book"][2]["author"].as() == "Herman Melville"); + + std::size_t count = jsonpath::erase(doc, loc); + + CHECK(count == 0); + CHECK(doc["store"]["book"].size() == 3); + CHECK(doc["store"]["book"][2]["author"].as() == "Herman Melville"); + } + + SECTION("store") + { + jsonpath::json_location loc; + loc.append("store"); + + std::size_t count = jsonpath::erase(doc, loc); + CHECK(count == 1); + CHECK(doc.size() == 0); + } + + SECTION("store book") + { + jsonpath::json_location loc; + loc.append("store").append("book"); + + CHECK(doc["store"]["book"].size() == 3); + std::size_t count = jsonpath::erase(doc, loc); + CHECK(count == 1); + CHECK(doc["store"]["book"].size() == 0); + } + + SECTION("store lost&found") + { + jsonpath::json_location loc; + loc.append("store").append("lost&found"); + + CHECK(doc["store"].size() == 1); + std::size_t count = jsonpath::erase(doc, loc); + CHECK(count == 0); + CHECK(doc["store"].size() == 1); + } + + SECTION("store book 2 price") + { + jsonpath::json_location loc; + loc.append("store").append("book").append(2).append("price"); + + + CHECK(doc["store"]["book"].size() == 3); + CHECK(doc["store"]["book"][2]["author"].as() == "Herman Melville"); + CHECK(doc["store"]["book"][2].contains("price")); + + std::size_t count = jsonpath::erase(doc, loc); + + CHECK(count == 1); + CHECK(doc["store"]["book"].size() == 3); + CHECK(doc["store"]["book"][2]["author"].as() == "Herman Melville"); + CHECK_FALSE(doc["store"]["book"][2].contains("price")); + } +} +