blob: 39597877e9725a064cd6170d3f04dd7ffdb503e7 [file] [log] [blame]
[[jsonpath-language]]
= JsonPath Language
:page-source: components/camel-jsonpath/src/main/docs/jsonpath-language.adoc
*Since Camel 2.13*
Camel supports https://code.google.com/p/json-path/[JSonPath] to allow
using Expression or Predicate
on json messages.
[source,java]
-----------------------------------------------------
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")
-----------------------------------------------------
== JSonPath Options
// language options: START
The JsonPath language supports 7 options, which are listed below.
[width="100%",cols="2,1m,1m,6",options="header"]
|===
| Name | Default | Java Type | Description
| resultType | | String | Sets the class name of the result type (type from output)
| suppressExceptions | false | Boolean | Whether to suppress exceptions such as PathNotFoundException.
| allowSimple | true | Boolean | Whether to allow in inlined simple exceptions in the JsonPath expression
| allowEasyPredicate | true | Boolean | Whether to allow using the easy predicate parser to pre-parse predicates.
| writeAsString | false | Boolean | Whether to write the output of each row/element as a JSON String value instead of a Map/POJO value.
| headerName | | String | Name of header to use as input, instead of the message body
| trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks
|===
// language options: END
// spring-boot-auto-configure options: START
== Spring Boot Auto-Configuration
When using Spring Boot make sure to use the following Maven dependency to have support for auto configuration:
[source,xml]
----
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jsonpath-starter</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>
----
The component supports 7 options, which are listed below.
[width="100%",cols="2,5,^1,2",options="header"]
|===
| Name | Description | Default | Type
| *camel.language.jsonpath.allow-easy-predicate* | Whether to allow using the easy predicate parser to pre-parse predicates. | true | Boolean
| *camel.language.jsonpath.allow-simple* | Whether to allow in inlined simple exceptions in the JsonPath expression | true | Boolean
| *camel.language.jsonpath.enabled* | Enable jsonpath language | true | Boolean
| *camel.language.jsonpath.header-name* | Name of header to use as input, instead of the message body | | String
| *camel.language.jsonpath.suppress-exceptions* | Whether to suppress exceptions such as PathNotFoundException. | false | Boolean
| *camel.language.jsonpath.trim* | Whether to trim the value to remove leading and trailing whitespaces and line breaks | true | Boolean
| *camel.language.jsonpath.write-as-string* | Whether to write the output of each row/element as a JSON String value instead of a Map/POJO value. | false | Boolean
|===
// spring-boot-auto-configure options: END
== Using XML configuration
If you prefer to configure your routes in your Spring
XML file then you can use xref:jsonpath-language.adoc[JSonPath] expressions as
follows
[source,xml]
----
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:start"/>
<choice>
<when>
<jsonpath>$.store.book[?(@.price &lt; 10)]</jsonpath>
<to uri="mock:cheap"/>
</when>
<when>
<jsonpath>$.store.book[?(@.price &lt; 30)]</jsonpath>
<to uri="mock:average"/>
</when>
<otherwise>
<to uri="mock:expensive"/>
</otherwise>
</choice>
</route>
</camelContext>
----
== Syntax
See the https://code.google.com/p/json-path/[JSonPath] project page for
further examples.
== Easy Syntax
*Since Camel 2.19*
When you just want to define a basic predicate using jsonpath syntax it can be a bit hard to remember the syntax.
So for example to find out all the cheap books you have to do
----
$.store.book[?(@.price < 20)]
----
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 define 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}
----
== Supported message body types
Camel JSonPath supports message body using the following types:
[width="100%",cols="3m,7",options="header"]
|===
| Type | Comment
| File | Reading from files
| String | Plain strings
| Map | Message bodies as `java.util.Map` types
| List | Message bodies as `java.util.List` types
| POJO | *Optional* If Jackson is on the classpath, then camel-jsonpath
is able to use Jackson to read the message body as POJO and convert to `java.util.Map`
which is supported by JSonPath. For example you can add `camel-jackson` as dependency to include Jackson.
| InputStream | If none of the above types matches, then Camel will attempt to read the message body as an `java.io.InputStream`.
|===
If a message body is of unsupported type then an exception is thrown by default, however you
can configure JSonPath to suppress exceptions (see below)
== Suppress exceptions
*Since Camel 2.16*
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
suppressExceptions to true to ignore this as shown:
[source,java]
----
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:
[source,xml]
----
<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>
----
This option is also available on the `@JsonPath` annotation.
== Inline Simple exceptions
*Since Camel 2.18*
Its now possible to inlined Simple language expressions in the JSonPath expression using the simple syntax $\{xxx\}.
An example is shown below:
[source,java]
----
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:
[source,xml]
----
<route>
<from uri="direct:start"/>
<choice>
<when>
<jsonpath>$.store.book[?(@.price < ${header.cheap})]</jsonpath>
<to uri="mock:cheap"/>
</when>
<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 allowSimple to false as shown:
[source,java]
----
.when().jsonpath("$.store.book[?(@.price < 10)]", false, false)
----
And in XML DSL:
[source,xml]
----
<jsonpath allowSimple="false">$.store.book[?(@.price < 10)]</jsonpath>
----
== JSonPath injection
You can use Bean Integration to invoke a
method on a bean and use various languages such as JSonPath to extract a
value from the message and bind it to a method parameter.
For example
[source,java]
----
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
}
}
----
== 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 the JSONPath component or you
can specify the encoding in the header "*CamelJsonPathJsonEncoding*"
(JsonpathConstants.HEADER_JSON_ENCODING).
== Split JSon data into sub rows as JSon
You can use jsonpath to split a JSon document, such as:
[source,java]
----
from("direct:start")
.split().jsonpath("$.store.book[*]")
.to("log:book");
----
Then each book is logged, however the message body is a `Map` instance. Sometimes
you may want to output this as plain String JSon value instead, which can be done
with the `writeAsString` option as shown:
[source,java]
----
from("direct:start")
.split().jsonpathWriteAsString("$.store.book[*]")
.to("log:book");
----
Then each book is logged as a String JSon value. For earlier versions of Camel you
would need to use camel-jackson dataformat and marshal the message body to make it
convert the message body from `Map` to a `String` type.
== Using header as input
*Since Camel 2.20*
By default jsonpath uses the message body as the input source. However you can also use a header as input
by specifying the `headerName` option.
For example to count the number of books from a json document that
was stored in a header named `books` you can do:
[source,java]
----
from("direct:start")
.setHeader("numberOfBooks")
.jsonpath("$..store.book.length()", false, int.class, "books")
.to("mock:result");
----
In the `jsonpath` expression above we specify the name of the header as `books`
and we also told that we wanted the result to be converted as an integer by `int.class`.
The same example in XML DSL would be:
[source,xml]
----
<route>
<from uri="direct:start"/>
<setHeader name="numberOfBooks">
<jsonpath headerName="books" resultType="int">$..store.book.length()</jsonpath>
</transform>
<to uri="mock:result"/>
</route>
----
== Dependencies
To use JSonPath in your camel routes you need to add the a dependency on
*camel-jsonpath* which implements the JSonPath language.
If you use maven you could just add the following to your pom.xml,
substituting the version number for the latest & greatest release (see
the download page for the latest versions).
[source,xml]
----
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jsonpath</artifactId>
<version>x.x.x</version>
</dependency>
----