Skip to content

Commit

Permalink
make_expression doc
Browse files Browse the repository at this point in the history
  • Loading branch information
danielaparker committed Nov 21, 2023
1 parent 27b10ae commit 258f856
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 22 deletions.
100 changes: 96 additions & 4 deletions doc/ref/jsonpath/make_expression.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jsonpath_expression<Json> make_expression(const Json::string_view_type& expr,
```cpp
template <class Json>
jsonpath_expression<Json> make_expression(const Json::string_view_type& expr,
const custom_functions<Json>& funcs, std::error_code& ec); (3) (since 0.164.0)
const custom_functions<Json>& funcs, std::error_code& ec); (3) (since 0.164.0)
```
```cpp
template <class Json, class TempAllocator> (4) (since 0.170.0)
Expand Down Expand Up @@ -108,6 +108,12 @@ The examples below uses the sample data file `books.json`,
#### Return copies

```cpp
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using json = jsoncons::json;
namespace jsonpath = jsoncons::jsonpath;

int main()
{
auto expr = jsonpath::make_expression<json>("$.books[?(@.price > avg($.books[*].price))].title");
Expand All @@ -126,20 +132,104 @@ Output:
]
```

#### Return locations of selected values (since 0.172.0)

```cpp
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using json = jsoncons::json;
namespace jsonpath = jsoncons::jsonpath;

int main()
{
auto expr = jsoncons::jsonpath::make_expression<json>("$.books[*]");

std::ifstream is("./input/books.json");
json doc = json::parse(is);

std::vector<jsonpath::json_location> paths = expr.select_paths(doc);
for (const auto& path : paths)
{
std::cout << jsonpath::to_string(path) << "\n";
}
}
```
Output:
```
[
$['books'][0]
$['books'][1]
$['books'][2]
$['books'][3]
]
```

#### Update in place (since 0.172.0)

```cpp
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using json = jsoncons::json;
namespace jsonpath = jsoncons::jsonpath;

int main()
{
auto expr = jsoncons::jsonpath::make_expression<json>("$.books[*]");

std::ifstream is("./input/books.json");
json doc = json::parse(is);

auto callback = [](const jsonpath::path_node& /*location*/, json& book)
{
if (book.at("category") == "memoir" && !book.contains("price"))
{
book.try_emplace("price", 140.0);
}
};

expr.update(doc, callback);
}
```
Output:
```
{
"author": "Phillips, David Atlee",
"category": "memoir",
"price": 140.0,
"title": "The Night Watch"
}
```

#### Access path and reference to original value

```cpp
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>

using json = jsoncons::json;
namespace jsonpath = jsoncons::jsonpath;

int main()
{
auto expr = jsonpath::make_expression<json>("$.books[?(@.price >= 22.0)]");

std::ifstream is("./input/books.json");
json data = json::parse(is);

auto callback = [](const std::string& path, const json& val)
// legacy (deprecated in 0.172.0)
// auto callback = [](const std::string& path, const json& val)
// {
// std::cout << path << ": " << val << "\n";
// };

// since 0.172.0
auto callback = [](const jsonpath::path_node& path, const json& val)
{
std::cout << path << ": " << val << "\n";
std::cout << jsonpath::to_string(path) << ": " << val << "\n";
};

expr.evaluate(data, callback, jsonpath::result_options::path);
}
```
Expand Down Expand Up @@ -210,6 +300,8 @@ Output:
using my_alloc = FreeListAllocator<char>; // an allocator with a single-argument constructor
using my_json = jsoncons::basic_json<char,jsoncons::sorted_policy,my_alloc>;

namespace jsonpath = jsoncons::jsonpath;

int main()
{
auto alloc = my_alloc(1);
Expand All @@ -229,7 +321,7 @@ int main()
my_json doc = decoder.get_result();

std::string_view p{"$.books[?(@.category == 'fiction')].title"};
auto expr = jsoncons::jsonpath::make_expression<my_json>(combine_allocators(alloc), p);
auto expr = jsonpath::make_expression<my_json>(combine_allocators(alloc), p);
auto result = expr.evaluate(doc);

std::cout << pretty_print(result) << "\n\n";
Expand Down
42 changes: 24 additions & 18 deletions test/jsonpath/src/jsonpath_make_expression_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,40 +74,45 @@ TEST_CASE("jsonpath make_expression tests")
CHECK_FALSE(doc["books"][3].contains("price"));
}

SECTION("test 2")
SECTION("Update in place")
{
int count = 0;

json doc = json::parse(input);

auto expr = jsoncons::jsonpath::make_expression<json>("$.books[*]");

auto callback1 = [&](const jsonpath::path_node& /*location*/, const json& book)
{
if (book.at("category") == "memoir" && !book.contains("price"))
{
++count;
}
};

auto callback2 = [](const jsonpath::path_node& /*location*/, json& book)
auto callback = [](const jsonpath::path_node& /*location*/, json& book)
{
if (book.at("category") == "memoir" && !book.contains("price"))
{
book.try_emplace("price", 140.0);
}
};

expr.select(doc, callback1);

CHECK(count == 1);
expr.update(doc, callback);

CHECK_FALSE(doc["books"][3].contains("price"));
expr.update(doc, callback2);
CHECK(doc["books"][3].contains("price"));
CHECK(doc["books"][3].at("price") == 140);
}

SECTION("Return locations of selected values")
{
json doc = json::parse(input);

auto expr = jsoncons::jsonpath::make_expression<json>("$.books[*]");

std::vector<jsonpath::json_location> paths = expr.select_paths(doc);

REQUIRE(paths.size() == 4);
CHECK(jsonpath::to_string(paths[0]) == "$['books'][0]");
CHECK(jsonpath::to_string(paths[1]) == "$['books'][1]");
CHECK(jsonpath::to_string(paths[2]) == "$['books'][2]");
CHECK(jsonpath::to_string(paths[3]) == "$['books'][3]");
//for (const auto& path : paths)
//{
// std::cout << jsonpath::to_string(path) << "\n";
//}
}

SECTION("update default sort order")
{
json doc = json::parse(input);
Expand Down Expand Up @@ -168,6 +173,7 @@ TEST_CASE("jsonpath legacy make_expression test")
int count = 0;

const json doc = json::parse(input);
const json original = doc;

auto expr = jsoncons::jsonpath::make_expression<json>("$.books[*]");

Expand All @@ -182,7 +188,7 @@ TEST_CASE("jsonpath legacy make_expression test")
expr.evaluate(doc, callback);

CHECK(count == 1);
CHECK_FALSE(doc["books"][3].contains("price"));
CHECK(doc == original);
}
}

0 comments on commit 258f856

Please sign in to comment.