| [[jsonpath-language]] |
| = JsonPath Language |
| :page-source: components/camel-jsonpath/src/main/docs/jsonpath-language.adoc |
| |
| *Available as of Camel version 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</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 < 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> |
| ---- |
| |
| == Syntax |
| |
| See the https://code.google.com/p/json-path/[JSonPath] project page for |
| further examples. |
| |
| == Easy Syntax |
| |
| *Available as of 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 |
| |
| *Available as of 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 |
| |
| *Available as of 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 |
| *Available as of 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> |
| ---- |