Skip to content

Commit

Permalink
make_update_expression
Browse files Browse the repository at this point in the history
  • Loading branch information
danielaparker committed Nov 3, 2023
1 parent 00e9889 commit c5e7eee
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 25 deletions.
2 changes: 1 addition & 1 deletion doc/Examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -3784,7 +3784,7 @@ int main()
jsonpath::json_replace(j,"$.books[?(@.isbn == '0553213113')].price",10.0);

// Increase the price of "Sayings of the Century" by $1
auto f = [](const std::string& /*path*/, json& value)
auto f = [](const std::string& /*location*/, json& value)
{
value = value.as<double>() + 1.0;
};
Expand Down
4 changes: 2 additions & 2 deletions doc/ref/jsonpath/json_replace.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ int main()
std::ifstream is("./input/books.json");
json data = json::parse(is);

auto f = [](const std::string& /*path*/, json& price)
auto f = [](const std::string& /*location*/, json& price)
{
price = std::round(price.as<double>() - 1.0);
};
Expand Down Expand Up @@ -249,7 +249,7 @@ int main()
std::ifstream is("./input/books.json");
json data = json::parse(is);

auto f = [](const std::string& /*path*/, json& book)
auto f = [](const std::string& /*location*/, json& book)
{
if (book.at("category") == "memoir" && !book.contains("price"))
{
Expand Down
2 changes: 1 addition & 1 deletion doc/ref/jsonpath/jsonpath.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ int main()
std::ifstream is("./input/books.json");
json data = json::parse(is);
auto f = [](const std::string& /*path*/, json& price)
auto f = [](const std::string& /*location*/, json& price)
{
price = std::round(price.as<double>() - 1.0);
};
Expand Down
6 changes: 3 additions & 3 deletions examples/src/jsonpath_examples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ void json_replace_example3()
std::ifstream is("./input/books.json");
json data = json::parse(is);

auto f = [](const std::string& /*path*/, json& price)
auto f = [](const std::string& /*location*/, json& price)
{
price = std::round(price.as<double>() - 1.0);
};
Expand All @@ -388,7 +388,7 @@ void json_replace_example4()
std::ifstream is("./input/books.json");
json data = json::parse(is);

auto f = [](const std::string& /*path*/, json& book)
auto f = [](const std::string& /*location*/, json& book)
{
if (book.at("category") == "memoir" && !book.contains("price"))
{
Expand Down Expand Up @@ -701,7 +701,7 @@ void search_for_and_replace_a_value()
jsonpath::json_replace(j,"$.books[?(@.isbn == '0553213113')].price",10.0);

// Increase the price of "Sayings of the Century" by $1
auto f = [](const std::string& /*path*/, json& value)
auto f = [](const std::string& /*location*/, json& value)
{
value = value.as<double>() + 1.0;
};
Expand Down
10 changes: 5 additions & 5 deletions include/jsoncons_ext/jsonpath/json_query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ namespace jsonpath {
json_replace(Json& instance, const typename Json::string_view_type& path, T&& new_value,
const custom_functions<Json>& funcs = custom_functions<Json>())
{
using jsonpath_traits_type = jsoncons::jsonpath::detail::jsonpath_traits<Json, Json&>;
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json, Json&>;

using value_type = typename jsonpath_traits_type::value_type;
using reference = typename jsonpath_traits_type::reference;
Expand All @@ -88,7 +88,7 @@ namespace jsonpath {
Json& instance, const typename Json::string_view_type& path, T&& new_value,
const custom_functions<Json>& funcs = custom_functions<Json>())
{
using jsonpath_traits_type = jsoncons::jsonpath::detail::jsonpath_traits<Json, Json&>;
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json, Json&>;

using value_type = typename jsonpath_traits_type::value_type;
using reference = typename jsonpath_traits_type::reference;
Expand All @@ -113,7 +113,7 @@ namespace jsonpath {
json_replace(Json& instance, const typename Json::string_view_type& path , BinaryCallback callback,
const custom_functions<Json>& funcs = custom_functions<Json>())
{
using jsonpath_traits_type = jsoncons::jsonpath::detail::jsonpath_traits<Json, Json&>;
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json, Json&>;

using value_type = typename jsonpath_traits_type::value_type;
using reference = typename jsonpath_traits_type::reference;
Expand All @@ -140,7 +140,7 @@ namespace jsonpath {
Json& instance, const typename Json::string_view_type& path , BinaryCallback callback,
const custom_functions<Json>& funcs = custom_functions<Json>())
{
using jsonpath_traits_type = jsoncons::jsonpath::detail::jsonpath_traits<Json, Json&>;
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json, Json&>;

using value_type = typename jsonpath_traits_type::value_type;
using reference = typename jsonpath_traits_type::reference;
Expand All @@ -166,7 +166,7 @@ namespace jsonpath {
typename std::enable_if<extension_traits::is_unary_function_object<UnaryCallback,Json>::value,void>::type
json_replace(Json& instance, const typename Json::string_view_type& path , UnaryCallback callback)
{
using jsonpath_traits_type = jsoncons::jsonpath::detail::jsonpath_traits<Json, Json&>;
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json, Json&>;

using value_type = typename jsonpath_traits_type::value_type;
using reference = typename jsonpath_traits_type::reference;
Expand Down
94 changes: 84 additions & 10 deletions include/jsoncons_ext/jsonpath/jsonpath_expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2481,6 +2481,8 @@ namespace detail {
}
};

} // namespace detail

template <class Json, class JsonReference = const Json&>
struct jsonpath_traits
{
Expand All @@ -2495,17 +2497,15 @@ namespace detail {
using evaluator_type = typename jsoncons::jsonpath::detail::jsonpath_evaluator<value_type, reference>;
using path_node_type = path_node<string_type>;
using json_location_type = json_location<string_type>;
using path_expression_type = path_expression<value_type,reference>;
using path_expression_type = jsoncons::jsonpath::detail::path_expression<value_type,reference>;
using path_pointer = const path_node_type*;
};

} // namespace detail

template <class Json,class JsonReference = const Json&, class TempAllocator=std::allocator<char>>
class jsonpath_expression
{
public:
using jsonpath_traits_type = jsoncons::jsonpath::detail::jsonpath_traits<Json, JsonReference>;
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json, JsonReference>;

using allocator_type = typename jsonpath_traits_type::allocator_type;
using evaluator_type = typename jsonpath_traits_type::evaluator_type;
Expand Down Expand Up @@ -2583,6 +2583,80 @@ namespace detail {
}
};

template <class Json,class JsonReference = const Json&, class TempAllocator=std::allocator<char>>
class update_expression
{
public:
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json, JsonReference>;

using allocator_type = typename jsonpath_traits_type::allocator_type;
using evaluator_type = typename jsonpath_traits_type::evaluator_type;
using char_type = typename jsonpath_traits_type::char_type;
using string_type = typename jsonpath_traits_type::string_type;
using string_view_type = typename jsonpath_traits_type::string_view_type;
using value_type = typename jsonpath_traits_type::value_type;
using reference = typename jsonpath_traits_type::reference;
using const_reference = typename jsonpath_traits_type::const_reference;
using path_expression_type = typename jsonpath_traits_type::path_expression_type;
using json_location_type = typename jsonpath_traits_type::json_location_type;
private:
allocator_type alloc_;
std::unique_ptr<jsoncons::jsonpath::detail::static_resources<value_type,reference>> static_resources_;
path_expression_type expr_;
public:
update_expression(const allocator_set<allocator_type,TempAllocator>& alloc_set,
std::unique_ptr<jsoncons::jsonpath::detail::static_resources<value_type,reference>>&& resources,
path_expression_type&& expr)
: alloc_(alloc_set.get_allocator()),
static_resources_(std::move(resources)),
expr_(std::move(expr))
{
}

update_expression(const update_expression&) = delete;
update_expression(update_expression&&) = default;

update_expression& operator=(const update_expression&) = delete;
update_expression& operator=(update_expression&&) = default;

template <class BinaryCallback>
typename std::enable_if<extension_traits::is_binary_function_object<BinaryCallback,const json_location_type&,const_reference>::value,void>::type
evaluate(reference instance, BinaryCallback callback, result_options options = result_options()) const
{
jsoncons::jsonpath::detail::dynamic_resources<value_type,reference> resources{alloc_};
expr_.evaluate(resources, instance, resources.root_path_node(), instance, callback, options);
}

value_type evaluate(reference instance, result_options options = result_options()) const
{
if ((options & result_options::path) == result_options::path)
{
jsoncons::jsonpath::detail::dynamic_resources<value_type,reference> resources{alloc_};

value_type result(json_array_arg, semantic_tag::none, alloc_);
auto callback = [&result](const json_location_type& p, reference)
{
result.emplace_back(p.to_string());
};
expr_.evaluate(resources, instance, resources.root_path_node(), instance, callback, options);
return result;
}
else
{
jsoncons::jsonpath::detail::dynamic_resources<value_type,reference> resources{alloc_};
return expr_.evaluate(resources, instance, resources.current_path_node(), instance, options);
}
}

template <class BinaryCallback>
typename std::enable_if<extension_traits::is_binary_function_object<BinaryCallback,const json_location_type&,value_type&>::value,void>::type
evaluate_and_update(reference instance, BinaryCallback callback) const
{
jsoncons::jsonpath::detail::dynamic_resources<value_type,reference> resources{alloc_};
expr_.evaluate_with_replacement(resources, instance, resources.root_path_node(), instance, callback);
}
};

template <class Json>
jsonpath_expression<Json> make_expression(const typename Json::string_view_type& expr,
const custom_functions<Json>& functions = custom_functions<Json>())
Expand Down Expand Up @@ -2616,7 +2690,7 @@ namespace detail {
const typename Json::string_view_type& path,
const custom_functions<Json>& functions = custom_functions<Json>())
{
using jsonpath_traits_type = jsoncons::jsonpath::detail::jsonpath_traits<Json>;
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json>;

using value_type = typename jsonpath_traits_type::value_type;
using reference = typename jsonpath_traits_type::reference;
Expand All @@ -2637,7 +2711,7 @@ namespace detail {
const typename Json::string_view_type& path,
const custom_functions<Json>& functions, std::error_code& ec)
{
using jsonpath_traits_type = jsoncons::jsonpath::detail::jsonpath_traits<Json>;
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json>;

using value_type = typename jsonpath_traits_type::value_type;
using reference = typename jsonpath_traits_type::reference;
Expand All @@ -2656,7 +2730,7 @@ namespace detail {
auto make_update_expression(const typename Json::string_view_type& path,
const jsoncons::jsonpath::custom_functions<Json>& funcs = jsoncons::jsonpath::custom_functions<Json>())
{
using jsonpath_traits_type = jsoncons::jsonpath::detail::jsonpath_traits<Json, Json&>;
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json, Json&>;

using value_type = typename jsonpath_traits_type::value_type;
using reference = typename jsonpath_traits_type::reference;
Expand All @@ -2666,15 +2740,15 @@ namespace detail {
evaluator_type evaluator;
auto expr = evaluator.compile(*static_resources, path);

return jsoncons::jsonpath::jsonpath_expression<value_type,reference>(jsoncons::combine_allocators(), std::move(static_resources), std::move(expr));
return jsoncons::jsonpath::update_expression<value_type,reference>(jsoncons::combine_allocators(), std::move(static_resources), std::move(expr));
}

template <class Json, class TempAllocator>
auto make_update_expression(const allocator_set<typename Json::allocator_type,TempAllocator>& alloc_set,
const typename Json::string_view_type& path,
const jsoncons::jsonpath::custom_functions<Json>& funcs, std::error_code& ec)
{
using jsonpath_traits_type = jsoncons::jsonpath::detail::jsonpath_traits<Json, Json&>;
using jsonpath_traits_type = jsoncons::jsonpath::jsonpath_traits<Json, Json&>;

using value_type = typename jsonpath_traits_type::value_type;
using reference = typename jsonpath_traits_type::reference;
Expand All @@ -2685,7 +2759,7 @@ namespace detail {
evaluator_type evaluator{alloc_set.get_allocator()};
auto expr = evaluator.compile(*static_resources, path, ec);

return jsoncons::jsonpath::jsonpath_expression<value_type,reference>(alloc_set, std::move(static_resources), std::move(expr));
return jsoncons::jsonpath::update_expression<value_type,reference>(alloc_set, std::move(static_resources), std::move(expr));
}

} // namespace jsonpath
Expand Down
6 changes: 3 additions & 3 deletions test/jsonpath/src/jsonpath_make_expression_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ TEST_CASE("jsonpath make_expression test")

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

auto callback = [&](const std::string& /*path*/, const json& book)
auto callback = [&](const jsonpath::json_location<std::string>& /*location*/, const json& book)
{
if (book.at("category") == "memoir" && !book.contains("price"))
{
Expand All @@ -82,15 +82,15 @@ TEST_CASE("jsonpath make_expression test")

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

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

auto callback2 = [](const std::string& /*path*/, json& book)
auto callback2 = [](const jsonpath::json_location<std::string>& /*location*/, json& book)
{
if (book.at("category") == "memoir" && !book.contains("price"))
{
Expand Down

0 comments on commit c5e7eee

Please sign in to comment.