Chapter 74. JSONPath
Camel supports JSONPath to allow using Expression or Predicate on JSON messages.
74.1. JSONPath Options
The JSONPath language supports 8 options, which are listed below.
Name | Default | Java Type | Description |
---|---|---|---|
resultType
|
74.2. Examples
For example, you can use JSONPath in a Predicate with the Content Based Router EIP .
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");
And in XML DSL:
<route> <from uri="direct:start"/> <choice> <jsonpath>$.store.book[?(@.price < 10)]</jsonpath> <to uri="mock:cheap"/> </when> <jsonpath>$.store.book[?(@.price < 30)]</jsonpath> <to uri="mock:average"/> </when> <otherwise> <to uri="mock:expensive"/> </otherwise> </choice> </route>
74.3. JSONPath Syntax
Using the JSONPath syntax takes some time to learn, even for basic predicates. So for example to find out all the cheap books you have to do:
$.store.book[?(@.price < 20)]
74.3.1. Easy JSONPath Syntax
However, what if you could just write it as:
store.book.price < 20
And you can 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 kicks-in if you have defined the predicate using a basic style. That means the predicate must not start with the
$
sign, and only include one operator.
The easy syntax is:
left OP right
You can use Camel simple language in the right operator, eg:
store.book.price < ${header.limit}
See the JSONPath project page for more syntax examples.
74.4. Supported message body types
Camel JSonPath supports message body using the following types:
Type | Comment | ||||
---|---|---|---|---|---|
Reading from files
74.5. Suppressing exceptions
By default, jsonpath will throw an exception if the json payload does not have a valid path accordingly to the configured jsonpath expression. In some use-cases you may want to ignore this in case the json payload contains optional data. Therefore, you can set the option
from("direct:start") .choice() // use true to suppress exceptions .when().jsonpath("person.middlename", true) .to("mock:middle") .otherwise() .to("mock:other"); And in XML DSL: <route> <from uri="direct:start"/> <choice> <jsonpath suppressExceptions="true">person.middlename</jsonpath> <to uri="mock:middle"/> </when> <otherwise> <to uri="mock:other"/> </otherwise> </choice> </route>
This option is also available on the
74.6. Inline Simple expressions
It’s possible to inlined
Simple
language in the JSONPath expression using the simple syntax
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"); And in XML DSL: <route> <from uri="direct:start"/> <choice> <jsonpath>$.store.book[?(@.price < ${header.cheap})]</jsonpath> <to uri="mock:cheap"/> </when> <jsonpath>$.store.book[?(@.price < ${header.average})]</jsonpath> <to uri="mock:average"/> </when> <otherwise> <to uri="mock:expensive"/> </otherwise> </choice> </route>
You can turn off support for inlined Simple expression by setting the option
.when().jsonpath("$.store.book[?(@.price < 10)]", false, false) And in XML DSL: <jsonpath allowSimple="false">$.store.book[?(@.price < 10)]</jsonpath> 74.7. JSonPath injection
You can use
Bean Integration
to invoke a method on a bean and use various languages such as JSONPath (via the
public class Foo { @Consume("activemq:queue:books.new") public void doSomething(@JsonPath("$.store.book[*].author") String author, @Body String json) { // process the inbound message here } 74.8. Encoding Detection
The encoding of the JSON document is detected automatically, if the document is encoded in unicode (UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE ) as specified in RFC-4627. If the encoding is a non-unicode encoding, you can either make sure that you enter the document in String format to JSONPath, or you can specify the encoding in the header
74.9. Split JSON data into sub rows as JSONYou can use JSONPath to split a JSON document, such as: from("direct:start") .split().jsonpath("$.store.book[*]") .to("log:book");
Then each book is logged, however the message body is a
from("direct:start") .split().jsonpathWriteAsString("$.store.book[*]") .to("log:book"); Then each book is logged as a String JSON value. 74.10. Using header as input
By default, JSONPath uses the message body as the input source. However, you can also use a header as input by specifying the
from("direct:start") .setHeader("numberOfBooks") .jsonpath("$..store.book.length()", false, int.class, "books") .to("mock:result");
In the
<route> <from uri="direct:start"/> <setHeader name="numberOfBooks"> <jsonpath headerName="books" resultType="int">$..store.book.length()</jsonpath> </setHeader> <to uri="mock:result"/> </route> 74.11. Spring Boot Auto-ConfigurationWhen using jsonpath with Spring Boot make sure to use the following Maven dependency to have support for auto configuration: <dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-jsonpath-starter</artifactId> </dependency> The component supports 8 options, which are listed below.
|