Skip to content

Commit

Permalink
json_location select
Browse files Browse the repository at this point in the history
  • Loading branch information
danielaparker committed Nov 16, 2023
1 parent 7033ee4 commit 9710ee3
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 14 deletions.
53 changes: 52 additions & 1 deletion include/jsoncons_ext/jsonpath/json_location.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ namespace jsonpath {
};

template<class Json>
std::size_t erase(Json& instance, const basic_json_location<typename Json::char_type>& location)
std::size_t remove(Json& instance, const basic_json_location<typename Json::char_type>& location)
{
std::size_t count = 0;

Expand Down Expand Up @@ -283,6 +283,57 @@ namespace jsonpath {
return count;
}

template<class Json>
Json* select(Json& instance, const basic_json_location<typename Json::char_type>& location)
{
Json* p_current = std::addressof(instance);
bool found = false;

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())
{
p_current = std::addressof(it->value());
if (i == last)
{
found = true;
}
}
else
{
break;
}
}
else
{
break;
}
}
else // if (element.has_index())
{
if (p_current->is_array() && element.index() < p_current->size())
{
p_current = std::addressof(p_current->at(element.index()));
if (i == last)
{
found = true;
}
}
else
{
break;
}
}
}
return found ? p_current : nullptr;
}

using json_location = basic_json_location<char>;
using wjson_location = basic_json_location<wchar_t>;
Expand Down
155 changes: 142 additions & 13 deletions test/jsonpath/src/json_location_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ TEST_CASE("json_location tests")
}
}


TEST_CASE("json_location erase tests")
TEST_CASE("json_location remove tests")
{

std::string json_string = R"(
Expand Down Expand Up @@ -62,7 +61,7 @@ TEST_CASE("json_location erase tests")
CHECK(doc["store"]["book"].size() == 3);
CHECK(doc["store"]["book"][1]["author"].as<std::string>() == "Evelyn Waugh");

std::size_t count = jsonpath::erase(doc, loc);
std::size_t count = jsonpath::remove(doc, loc);

CHECK(count == 1);
CHECK(doc["store"]["book"].size() == 2);
Expand All @@ -78,7 +77,7 @@ TEST_CASE("json_location erase tests")
CHECK(doc["store"]["book"].size() == 3);
CHECK(doc["store"]["book"][2]["author"].as<std::string>() == "Herman Melville");

std::size_t count = jsonpath::erase(doc, loc);
std::size_t count = jsonpath::remove(doc, loc);

CHECK(count == 1);
CHECK(doc["store"]["book"].size() == 2);
Expand All @@ -87,25 +86,26 @@ TEST_CASE("json_location erase tests")

SECTION("store book 3")
{
json orig = doc;

jsonpath::json_location loc;
loc.append("store").append("book").append(3);

CHECK(doc["store"]["book"].size() == 3);
CHECK(doc["store"]["book"][2]["author"].as<std::string>() == "Herman Melville");

std::size_t count = jsonpath::erase(doc, loc);
std::size_t count = jsonpath::remove(doc, loc);

CHECK(count == 0);
CHECK(doc["store"]["book"].size() == 3);
CHECK(doc["store"]["book"][2]["author"].as<std::string>() == "Herman Melville");
CHECK(doc == orig);
}

SECTION("store")
{
jsonpath::json_location loc;
loc.append("store");

std::size_t count = jsonpath::erase(doc, loc);
std::size_t count = jsonpath::remove(doc, loc);
CHECK(count == 1);
CHECK(doc.size() == 0);
}
Expand All @@ -116,38 +116,167 @@ TEST_CASE("json_location erase tests")
loc.append("store").append("book");

CHECK(doc["store"]["book"].size() == 3);
std::size_t count = jsonpath::erase(doc, loc);
std::size_t count = jsonpath::remove(doc, loc);
CHECK(count == 1);
CHECK(doc["store"]["book"].size() == 0);
}

SECTION("store lost&found")
{
json orig = doc;

jsonpath::json_location loc;
loc.append("store").append("lost&found");

CHECK(doc["store"].size() == 1);
std::size_t count = jsonpath::erase(doc, loc);
std::size_t count = jsonpath::remove(doc, loc);
CHECK(count == 0);
CHECK(doc["store"].size() == 1);
CHECK(doc == orig);
}

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<std::string>() == "Herman Melville");
CHECK(doc["store"]["book"][2].contains("price"));

std::size_t count = jsonpath::erase(doc, loc);
std::size_t count = jsonpath::remove(doc, loc);

CHECK(count == 1);
CHECK(doc["store"]["book"].size() == 3);
CHECK(doc["store"]["book"][2]["author"].as<std::string>() == "Herman Melville");
CHECK_FALSE(doc["store"]["book"][2].contains("price"));
}

SECTION("store 0")
{
json orig = doc;

jsonpath::json_location loc;
loc.append("store").append(0);

CHECK(doc["store"]["book"].size() == 3);
CHECK(doc["store"]["book"][2].contains("price"));

std::size_t count = jsonpath::remove(doc, loc);

CHECK(count == 0);
CHECK(doc == orig);
}
}

TEST_CASE("json_location select 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);

json* p_json = jsonpath::select(doc, loc);

CHECK_FALSE(p_json == nullptr);
CHECK(*p_json == doc.at("store").at("book").at(1));
}

SECTION("store book 2")
{
jsonpath::json_location loc;
loc.append("store").append("book").append(2);

json* p_json = jsonpath::select(doc, loc);

CHECK_FALSE(p_json == nullptr);
CHECK(*p_json == doc.at("store").at("book").at(2));
}

SECTION("store book 3")
{
jsonpath::json_location loc;
loc.append("store").append("book").append(3);

json* p_json = jsonpath::select(doc, loc);

CHECK(p_json == nullptr);
}

SECTION("store")
{
jsonpath::json_location loc;
loc.append("store");

json* p_json = jsonpath::select(doc, loc);
CHECK_FALSE(p_json == nullptr);
CHECK(*p_json == doc.at("store"));
}

SECTION("store book")
{
jsonpath::json_location loc;
loc.append("store").append("book");

json* p_json = jsonpath::select(doc, loc);
CHECK_FALSE(p_json == nullptr);
CHECK(*p_json == doc.at("store").at("book"));
}

SECTION("store lost&found")
{
jsonpath::json_location loc;
loc.append("store").append("lost&found");

json* p_json = jsonpath::select(doc, loc);
CHECK(p_json == nullptr);
}

SECTION("store book 2 price")
{
jsonpath::json_location loc;
loc.append("store").append("book").append(2).append("price");

json* p_json = jsonpath::select(doc, loc);

CHECK_FALSE(p_json == nullptr);
CHECK(*p_json == doc.at("store").at("book").at(2).at("price"));
}

SECTION("store 0")
{
jsonpath::json_location loc;
loc.append("store").append(0);

json* p_json = jsonpath::select(doc, loc);

CHECK(p_json == nullptr);
}
}

0 comments on commit 9710ee3

Please sign in to comment.