jmespath.cpp
C++ implementation of JMESPath, a query language for JSON http://jmespath.org
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
jmespath.cpp

jmespath.cpp is a C++ implementation of JMESPath, a query language for JSON. It can be used to extract and transform elements of a JSON document.

JMESPath expression example

Input JSON document:

{
"locations": [
{"name": "Seattle", "state": "WA"},
{"name": "New York", "state": "NY"},
{"name": "Bellevue", "state": "WA"},
{"name": "Olympia", "state": "WA"}
]
}

JMESPath expression:

locations[?state == 'WA'].name | sort(@) | {WashingtonCities: join(', ', @)}

Result of evaluating the expression:

{"WashingtonCities": "Bellevue, Olympia, Seattle"}

For more examples take a look at the JMESPath Tutorial or the JMESPath Examples pages.

Using jmespath.cpp

For installation instructions check out the Installation and integration page.

To use the public functions and classes of jmespath.cpp you should include the header file "#include \<jmespath/jmespath.h\>". The public interface is declared in the "jmespath" namespace.

#include <iostream>
namespace jp = jmespath;
int main(int argc, char *argv[])
{
auto data = R"({
"locations": [
{"name": "Seattle", "state": "WA"},
{"name": "New York", "state": "NY"},
{"name": "Bellevue", "state": "WA"},
{"name": "Olympia", "state": "WA"}
]
})"_json;
jp::Expression expression = "locations[?state == 'WA'].name | sort(@) | "
"{WashingtonCities: join(', ', @)}";
std::cout << jp::search(expression, data) << std::endl;
return 0;
}

Search function

The main entry point of the library is the jmespath::search function which takes a JMESPath expression as its first argument and a JSON document as the second argument and returns the result of the evaluated expression as a new JSON document.

auto input = R"({"foo": "bar"})"_json;
auto result = jmespath::search("foo", input);

Besided passing the input document as an lvalue reference you can also pass it as an rvalue reference, which would allow the library to take advantage of move operations internally and produce the output document in a more efficient and faster manner.

auto input = R"({"foo": "bar"})"_json;
auto result = jmespath::search("foo", std::move(input));

Expression class

The jmespath::Expression class allows to store a parsed JMESPath expression which is usefull if you want to evaluate the same expression on multiple JSON documents.

jmespath::Expression expression {"foo"};
auto result1 = jmespath::search(expression, R"({"foo": "bar"})"_json);
auto result2 = jmespath::search(expression, R"({"foo": {"bar": "baz"}})"_json);

By importing the names from the jmespath::literals namespace you can also use user defined literals to define JMESPath expressions.

using namespace jmespath::literals;
auto expression = "foo"_jmespath;
auto result1 = jmespath::search(expression, R"({"foo": "bar"})"_json);
auto result2 = jmespath::search(expression, R"({"foo": {"bar": "baz"}})"_json);

JSON documents

For the handling of JSON documents and values jmespath.cpp relies on the excelent nlohmann_json library.

For defining JSON values you can either use "_json" user defined literal or the jmespath::Json type which is just an alias for nlohmann_json

jmespath::Json jsonObject {{"foo", "bar"}};

or you can also include the header of the nlohmann_json library and use the "nlohmann::json" type directly.

#include <nlohmann/json.hpp>
nlohmann::json jsonObject {{"foo", "bar"}};

Error handling

All the exceptions that might get thrown by jmespath::search or jmespath::Expression are listed on the Exception classes page.

The library uses the Boost Exception library for throwing exceptions. Which means that the thrown exceptions can carry additional data attached to them. All the additional data that exceptions might carry is listed on the Error info types page.

This additional information can be used for example to pinpoint exactly which part of a JMESPath expression caused a parsing failure.

try
{
expression = "foo?";
}
catch (jmespath::SyntaxError& error)
{
if (const std::string* searchExpression
= boost::get_error_info<jmespath::InfoSearchExpression>(error))
{
std::cerr << "Failed parsing expression: "
<< *searchExpression << std::endl;
}
if (const long* location
= boost::get_error_info<jmespath::InfoSyntaxErrorLocation>(
error))
{
std::cerr << "Error at position: " << *location << std::endl;
}
}

This code would produce the following output:

Failed parsing expression: foo?
Error at position: 3

You can also use boost::diagnostic_information function to get all the additional information attached to an exception.

try
{
expression = "foo?";
}
catch (jmespath::SyntaxError& error)
{
std::cerr << boost::diagnostic_information(error) << std::endl;
}

This code would produce the following output:

jmespath.cpp/src/parser/parser.h(90): Throw in function jmespath::parser::Parser::ResultType jmespath::parser::Parser<parser::Grammar>::parse(const jmespath::String &) [T = parser::Grammar]
Dynamic exception type: boost::exception_detail::clone_impl<jmespath::SyntaxError>
std::exception::what: std::exception
[jmespath::tag_search_expression*] = foo?
[jmespath::tag_syntax_error_location*] = 3