Open mosswaldcognex opened 3 days ago
Yes, in 0.172.0 there were some changes to jsonpath::make_expression
, basically to support creating expressions that would allow update operations on the root JSON value, in addition to select. My goal was to make these changes entirely transparent to users, but it seems not to be the case for root json values containing json_const_pointer
elements.
You can still run this query by changing the template parameter in make_expression from jsoncons::json
to const jsoncons::json
, viz,
#include <jsoncons/json.hpp>
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
#include <iostream>
int main()
{
jsoncons::json root_works = jsoncons::json::parse(R"(
{
"books":
[
{
"category": "fiction",
"title" : "The Night Watch",
"author" : "Sergei Lukyanenko",
"price" : 23.58
},
{
"category": "fiction",
"title" : "The Comedians",
"author" : "Graham Greene",
"price" : 21.99
}
]
}
)");
jsoncons::json nested_json = jsoncons::json::parse(R"(
[
{
"category": "fiction",
"title" : "The Night Watch",
"author" : "Sergei Lukyanenko",
"price" : 23.58
},
{
"category": "fiction",
"title" : "The Comedians",
"author" : "Graham Greene",
"price" : 21.99
}
]
)");
jsoncons::json now_works = root_works;
now_works["books"] = jsoncons::json(jsoncons::json_const_pointer_arg, &nested_json);
auto expr = jsoncons::jsonpath::make_expression<const jsoncons::json>("$.books[?(@.price > avg($.books[*].price))].title");
try
{
jsoncons::json result_works = expr.evaluate(root_works);
jsoncons::json result_now_works = expr.evaluate(now_works);
std::cout << result_now_works << "\n";
}
catch (const std::exception& e)
{
std::cout << e.what() << "\n";
}
}
Output:
["The Night Watch"]
There's a bit of an issue with json_const_pointer_arg
because the root json value becomes half non-const, and half const. The compiler doesn't prevent you from calling functions like insert_or_assign
on the root, but the contained json_const_pointer
elements will throw on any except const function calls. It puts some burden on the user.
The next version (0.179.0) will support a json value containing non-const references to other json values, and you'll be able to write it as follows:
jsoncons::json now_works = root_works;
now_works["books"] = jsoncons::json(jsoncons::json_reference_arg, nested_json);
auto expr = jsoncons::jsonpath::make_expression<jsoncons::json>("$.books[?(@.price > avg($.books[*].price))].title");
try
{
jsoncons::json result_works = expr.evaluate(root_works);
jsoncons::json result_now_works = expr.evaluate(now_works);
std::cout << result_now_works << "\n";
}
catch (const std::exception& e)
{
std::cout << e.what() << "\n";
}
json_reference_arg
is currently supported on master. Unlike with json_const_pointer_arg
, all json functions and operators, both accessors and mutators, can be called on a json value containing json_reference_arg
elements. Mutators will mutate the referenced elements. And if you don't want mutation, you can always take a const reference to the value and work with that.
Many thanks for the detailed explanation! Sorry that I did not immediately recognize the change in 0.172.0. The problem is therefore solved for me. I will test the new value type json_reference_arg
at the next opportunity.
Calling
jsonpath_expression::evaluate()
on a JSON that contains ajson_const_pointer
to a valid second JSON throws "Index on non-array value not supported". The reason seems to be a non-const call tobasic_json::at[int i]
when selecting an array object.This behavior exist in the latest release 0.178.0. I used release 0.170.2 before which did not show this exception. There everything worked fine. The attached example_code.txt shows how to reproduce the error.