This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new 916f66f CAMEL-16861: Polished joor and jsonpath language 916f66f is described below commit 916f66f7b2c4a9611e21a736af4fd52540fa3e70 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Mon Sep 13 20:58:15 2021 +0200 CAMEL-16861: Polished joor and jsonpath language --- .../camel-joor/src/main/docs/joor-language.adoc | 15 +- .../org/apache/camel/jsonpath/jsonpath.json | 4 +- .../src/main/docs/jsonpath-language.adoc | 162 ++++++++++----------- .../org/apache/camel/model/language/jsonpath.json | 4 +- .../camel/model/language/JsonPathExpression.java | 4 +- 5 files changed, 90 insertions(+), 99 deletions(-) diff --git a/components/camel-joor/src/main/docs/joor-language.adoc b/components/camel-joor/src/main/docs/joor-language.adoc index dd3821e..8beefa9 100644 --- a/components/camel-joor/src/main/docs/joor-language.adoc +++ b/components/camel-joor/src/main/docs/joor-language.adoc @@ -9,12 +9,11 @@ include::{cq-version}@camel-quarkus:ROOT:partial$reference/languages/joor.adoc[o *Since Camel {since}* -The jOOR language allows to use Java code in your Camel expression, with some limitations. -The jOOR library integrates with the Java compiler and performs runtime compilation of Java code. +The jOOR language allows using Java code in your Camel expression, with some limitations. -NOTE: Java 8 is not supported. -Java 11 or 14 is required. +The jOOR library integrates with the Java compiler and performs runtime compilation of Java code. +NOTE: Java 8 is not supported. Java 11 is required. == jOOR Options @@ -77,7 +76,7 @@ Here we want to get the message body as a `com.foo.MyUser` type we can do as fol var user = bodyAs(com.foo.MyUser.class); ---- -You can omit _.class_ to make the function a little bit smaller: +You can omit _.class_ to make the function a little smaller: [source,java] ---- @@ -201,7 +200,7 @@ You can also add aliases (key=value) where an alias will be used as a shorthand echo()=bodyAs(String) + bodyAs(String) ---- -Which allows to use _echo()_ in the jOOR language script such as: +Which allows using _echo()_ in the jOOR language script such as: [source,java] ---- @@ -214,7 +213,7 @@ The _echo()_ alias will be replaced with its value resulting in a script as: [source,java] ---- - .transform(joor("'Hello ' + bodyAs(String) + bodyAs(String)")) +.transform(joor("'Hello ' + bodyAs(String) + bodyAs(String)")) ---- You can configure a custom configuration location for the `camel-joor.properties` file or reference to a bean in the registry: @@ -233,7 +232,7 @@ String config = "...."; camelContext.getRegistry().put("MyJoorConfig", config); ---- -== Sample +== Example For example to transform the message using jOOR language to upper case diff --git a/components/camel-jsonpath/src/generated/resources/org/apache/camel/jsonpath/jsonpath.json b/components/camel-jsonpath/src/generated/resources/org/apache/camel/jsonpath/jsonpath.json index e15a3aa..b79c9c1 100644 --- a/components/camel-jsonpath/src/generated/resources/org/apache/camel/jsonpath/jsonpath.json +++ b/components/camel-jsonpath/src/generated/resources/org/apache/camel/jsonpath/jsonpath.json @@ -19,11 +19,11 @@ "expression": { "kind": "value", "displayName": "Expression", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax" }, "resultType": { "kind": "attribute", "displayName": "Result Type", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the class name of the result type (type from output)" }, "suppressExceptions": { "kind": "attribute", "displayName": "Suppress Exceptions", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to suppress exceptions such as PathNotFoundException." }, - "allowSimple": { "kind": "attribute", "displayName": "Allow Simple", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow in inlined simple exceptions in the JsonPath expression" }, + "allowSimple": { "kind": "attribute", "displayName": "Allow Simple", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow in inlined Simple exceptions in the JSONPath expression" }, "allowEasyPredicate": { "kind": "attribute", "displayName": "Allow Easy Predicate", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow using the easy predicate parser to pre-parse predicates." }, "writeAsString": { "kind": "attribute", "displayName": "Write As String", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to write the output of each row\/element as a JSON String value instead of a Map\/POJO value." }, "headerName": { "kind": "attribute", "displayName": "Header Name", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of header to use as input, instead of the message body" }, - "option": { "kind": "attribute", "displayName": "Option", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "ALWAYS_RETURN_LIST", "AS_PATH_LIST", "DEFAULT_PATH_LEAF_TO_NULL", "REQUIRE_PROPERTIES", "SUPPRESS_EXCEPTIONS" ], "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional options on json path. Multiple values can be separated by comma." }, + "option": { "kind": "attribute", "displayName": "Option", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "ALWAYS_RETURN_LIST", "AS_PATH_LIST", "DEFAULT_PATH_LEAF_TO_NULL", "REQUIRE_PROPERTIES", "SUPPRESS_EXCEPTIONS" ], "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional options on JSONPath. Multiple values can be separated by comma." }, "trim": { "kind": "attribute", "displayName": "Trim", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to trim the value to remove leading and trailing whitespaces and line breaks" }, "id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" } } diff --git a/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc index 8995ae1..6a3d6e0 100644 --- a/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc +++ b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc @@ -9,23 +9,11 @@ include::{cq-version}@camel-quarkus:ROOT:partial$reference/languages/jsonpath.ad *Since Camel {since}* -Camel supports https://code.google.com/p/json-path/[JSonPath] to allow -using Expression or Predicate -on json messages. +Camel supports https://code.google.com/p/json-path/[JSONPath] to allow +using xref:manual::expression.adoc[Expression] or xref:manual::predicate.adoc[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 +== JSONPath Options // language options: START @@ -38,89 +26,100 @@ The JSONPath language supports 8 options, which are listed below. | 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 +| 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 -| option | | String | To configure additional options on json path. Multiple values can be separated by comma. +| option | | String | To configure additional options on JSONPath. Multiple values can be separated by comma. | trim | true | Boolean | Whether to trim the value to remove leading and trailing whitespaces and line breaks |=== // language options: END +== Examples +For example, you can use JSONPath in a xref:manual::predicate.adoc[Predicate] +with the xref:{eip-vc}:eips:choice-eip.adoc[Content Based Router] EIP. +[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"); +---- -== 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 +And in XML DSL: [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> +<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> ---- -== Syntax - -See the https://github.com/json-path/JsonPath[JSonPath] project page for -further examples. - -== Easy Syntax - -*Since Camel 2.19* +== JSONPath Syntax -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 +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: +[source,text] ---- $.store.book[?(@.price < 20)] ---- -However what if you could just write it as +=== Easy JSONPath Syntax +However, what if you could just write it as: + +[source,text] ---- store.book.price < 20 ---- -And you can omit the path if you just want to look at nodes with a price key +And you can omit the path if you just want to look at nodes with a price key: +[source,text] ---- 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. +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: +[source,text] ---- left OP right ---- -You can use Camel simple language in the right operator, eg +You can use Camel simple language in the right operator, eg: +[source,text] ---- store.book.price < ${header.limit} ---- +See the https://github.com/json-path/JsonPath[JSONPath] project page for more syntax examples. + + == Supported message body types Camel JSonPath supports message body using the following types: @@ -142,15 +141,13 @@ If a message body is of unsupported type then an exception is thrown by default, can configure JSonPath to suppress exceptions (see below) -== Suppress exceptions +== Suppressing exceptions -*Since Camel 2.16* - -By default jsonpath will throw an exception if the json payload does not +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: +contains optional data. Therefore, you can set the option +`suppressExceptions` to `true` to ignore this as shown: [source,java] ---- @@ -185,9 +182,9 @@ This option is also available on the `@JsonPath` annotation. == Inline Simple expressions -*Since Camel 2.18* +It's possible to inlined xref:languages:simple-language.adoc[Simple] language +in the JSONPath expression using the simple syntax `$\{xxx}`. -Its now possible to inlined Simple language expressions in the JSonPath expression using the simple syntax $\{xxx}. An example is shown below: [source,java] @@ -210,11 +207,11 @@ And in XML DSL: <from uri="direct:start"/> <choice> <when> - <jsonpath>$.store.book[?(@.price < ${header.cheap})]</jsonpath> + <jsonpath>$.store.book[?(@.price < ${header.cheap})]</jsonpath> <to uri="mock:cheap"/> </when> <when> - <jsonpath>$.store.book[?(@.price < ${header.average})]</jsonpath> + <jsonpath>$.store.book[?(@.price < ${header.average})]</jsonpath> <to uri="mock:average"/> </when> <otherwise> @@ -224,7 +221,7 @@ And in XML DSL: </route> ---- -You can turn off support for inlined simple expression by setting the option allowSimple to false as shown: +You can turn off support for inlined Simple expression by setting the option `allowSimple` to `false` as shown: [source,java] ---- @@ -235,16 +232,14 @@ And in XML DSL: [source,xml] ---- -<jsonpath allowSimple="false">$.store.book[?(@.price < 10)]</jsonpath> +<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 +You can use xref:manual::bean-integration.adoc[Bean Integration] to invoke a +method on a bean and use various languages such as JSONPath (via the `@JsonPath` annotation) +to extract a value from the message and bind it to a method parameter, as shown below: [source,java] ---- @@ -263,13 +258,13 @@ 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). +you enter the document in String format to JSONPath, or you +can specify the encoding in the header `CamelJsonPathJsonEncoding` which +is defined as a constant in: `JsonpathConstants.HEADER_JSON_ENCODING`. -== Split JSon data into sub rows as JSon +== Split JSON data into sub rows as JSON -You can use jsonpath to split a JSon document, such as: +You can use JSONPath to split a JSON document, such as: [source,java] ---- @@ -279,7 +274,7 @@ from("direct:start") ---- 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 +you may want to output this as plain String JSON value instead, which can be done with the `writeAsString` option as shown: [source,java] @@ -289,17 +284,14 @@ from("direct:start") .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. +Then each book is logged as a String JSON value. == 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 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 +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] @@ -310,7 +302,7 @@ from("direct:start") .to("mock:result"); ---- -In the `jsonpath` expression above we specify the name of the header as `books` +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: diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/language/jsonpath.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/language/jsonpath.json index 136041b..e332f19 100644 --- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/language/jsonpath.json +++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/language/jsonpath.json @@ -15,11 +15,11 @@ "expression": { "kind": "value", "displayName": "Expression", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax" }, "resultType": { "kind": "attribute", "displayName": "Result Type", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the class name of the result type (type from output)" }, "suppressExceptions": { "kind": "attribute", "displayName": "Suppress Exceptions", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to suppress exceptions such as PathNotFoundException." }, - "allowSimple": { "kind": "attribute", "displayName": "Allow Simple", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow in inlined simple exceptions in the JsonPath expression" }, + "allowSimple": { "kind": "attribute", "displayName": "Allow Simple", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow in inlined Simple exceptions in the JSONPath expression" }, "allowEasyPredicate": { "kind": "attribute", "displayName": "Allow Easy Predicate", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow using the easy predicate parser to pre-parse predicates." }, "writeAsString": { "kind": "attribute", "displayName": "Write As String", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to write the output of each row\/element as a JSON String value instead of a Map\/POJO value." }, "headerName": { "kind": "attribute", "displayName": "Header Name", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of header to use as input, instead of the message body" }, - "option": { "kind": "attribute", "displayName": "Option", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "ALWAYS_RETURN_LIST", "AS_PATH_LIST", "DEFAULT_PATH_LEAF_TO_NULL", "REQUIRE_PROPERTIES", "SUPPRESS_EXCEPTIONS" ], "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional options on json path. Multiple values can be separated by comma." }, + "option": { "kind": "attribute", "displayName": "Option", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "ALWAYS_RETURN_LIST", "AS_PATH_LIST", "DEFAULT_PATH_LEAF_TO_NULL", "REQUIRE_PROPERTIES", "SUPPRESS_EXCEPTIONS" ], "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional options on JSONPath. Multiple values can be separated by comma." }, "trim": { "kind": "attribute", "displayName": "Trim", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to trim the value to remove leading and trailing whitespaces and line breaks" }, "id": { "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" } } diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/language/JsonPathExpression.java b/core/camel-core-model/src/main/java/org/apache/camel/model/language/JsonPathExpression.java index 79e7d9d..766ec58 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/language/JsonPathExpression.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/language/JsonPathExpression.java @@ -92,7 +92,7 @@ public class JsonPathExpression extends ExpressionDefinition { } /** - * Whether to allow in inlined simple exceptions in the JsonPath expression + * Whether to allow in inlined Simple exceptions in the JSONPath expression */ public void setAllowSimple(String allowSimple) { this.allowSimple = allowSimple; @@ -143,7 +143,7 @@ public class JsonPathExpression extends ExpressionDefinition { } /** - * To configure additional options on json path. Multiple values can be separated by comma. + * To configure additional options on JSONPath. Multiple values can be separated by comma. */ public void setOption(String option) { this.option = option;