Chapter 21. JsonPath
Overview
The JsonPath language provides a convenient syntax for extracting portions of a JSON message. The syntax of JSON is similar to XPath, but it is used to extract JSON objects from a JSON message, instead of acting on XML. The jsonpath
DSL command can be used either as an expression or as a predicate (where an empty result gets interpreted as boolean false
).
Adding the JsonPath package
To use JsonPath in your Camel routes, you need to add a dependency on camel-jsonpath
to your project, as follows:
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jsonpath</artifactId> <version>${camel-version}</version> </dependency>
Java example
The following Java example shows how to use the jsonpath()
DSL command to select items in a certain price range:
from("queue:books.new") .choice() .when().jsonpath("$.store.book[?(@.price < 10)]") .to("jms:queue:book.cheap") .when().jsonpath("$.store.book[?(@.price < 30)]") .to("jms:queue:book.average") .otherwise() .to("jms:queue:book.expensive")
If the JsonPath query returns an empty set, the result is interpreted as false
. In this way, you can use a JsonPath query as a predicate.
XML example
The following XML example shows how to use the jsonpath
DSL element to define predicates in a route:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="direct:start"/> <choice> <when> <jsonpath>$.store.book[?(@.price < 10)]</jsonpath> <to uri="mock:cheap"/> </when> <when> <jsonpath>$.store.book[?(@.price < 30)]</jsonpath> <to uri="mock:average"/> </when> <otherwise> <to uri="mock:expensive"/> </otherwise> </choice> </route> </camelContext>
Easy Syntax
When you wish to define a basic predicate using jsonpath
syntax it can be a bit hard to remember the syntax. For example, to find out all the cheap books, you have to write the syntax as follows:
$.store.book[?(@.price < 20)]
However, what if you could just write it as:
store.book.price < 20
You can also omit the path if you just want to look at nodes with a price key:
price < 20
To support this, there is a EasyPredicateParser
which you use to define the predicate using a basic style. That means the predicate must not start with the $
sign, and must include only one operator. The easy syntax is as follows:
left OP right
You can use Camel simple language in the right operator, for example,
store.book.price < ${header.limit}
Supported Message Body Types
Camel JSonPath supports message body using the following types:
Type | Description |
---|---|
File | Reading from files |
String | Plain strings |
Map |
essage body as |
List | Message body as java.util.List type |
|
Optional If Jackson is on the classpath, then |
|
If none of the above types matches, then Camel will attempt to read the message body as an |
If a message body is of unsupported type then an exception is thrown by default, however you can configure JSonPath to suppress exceptions.
Suppress Exceptions
JsonPath will throw an exception if the path configured by the jsonpath
expression is not found. The exception can be ignored by setting the SuppressExceptions
option to true. For example, in the code below, adding the true option as part of the jsonpath
parameters:
from("direct:start")
.choice()
// use true to suppress exceptions
.when().jsonpath("person.middlename", true
)
.to("mock:middle")
.otherwise()
.to("mock:other");
In XML DSL use the following syntax:
<route> <from uri="direct:start"/> <choice> <when> <jsonpath suppressExceptions="true">person.middlename</jsonpath> <to uri="mock:middle"/> </when> <otherwise> <to uri="mock:other"/> </otherwise> </choice> </route>
JsonPath injection
When using bean integration to invoke a bean method, you can use JsonPath to extract a value from the message and bind it to a method parameter. For example:
// Java public class Foo { @Consume(uri = "activemq:queue:books.new") public void doSomething(@JsonPath("$.store.book[*].author") String author, @Body String json) { // process the inbound message here } }
Inline Simple Expressions
New in Camel 2.18.
Camel supports inline Simple
expressions in the JsonPath
expressions. The Simple
language insertions must be expressed in Simple
syntax as shown below:
from("direct:start") .choice() .when().jsonpath("$.store.book[?(@.price < `${header.cheap}`)]") .to("mock:cheap") .when().jsonpath("$.store.book[?(@.price < `${header.average}`)]") .to("mock:average") .otherwise() .to("mock:expensive");
Turn off support for Simple
expressions by setting the option allowSimple=false
as shown below.
Java:
// Java DSL .when().jsonpath("$.store.book[?(@.price < 10)]", `false, false`)
XML DSL:
// XML DSL <jsonpath allowSimple="false">$.store.book[?(@.price < 10)]</jsonpath>
Reference
For more details about JsonPath, see the JSonPath project page.