This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch jp in repository https://gitbox.apache.org/repos/asf/camel.git
commit dbc4968476f580d92506641105cb74c3205cb9ca Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Sun Nov 26 13:25:57 2023 +0100 CAMEL-20154: camel-jsonpath - Make it easier to grab elements in a template like fashion --- .../src/main/docs/jsonpath-language.adoc | 27 ++++++++++ .../jsonpath/JsonPathSimpleTransformTest.java | 59 ++++++++++++++++++++++ .../modules/languages/pages/simple-language.adoc | 3 ++ .../simple/ast/SimpleFunctionExpression.java | 10 ++++ 4 files changed, 99 insertions(+) diff --git a/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc index 1da4bd1d8e7..b73e2177370 100644 --- a/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc +++ b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc @@ -318,5 +318,32 @@ The same example in XML DSL would be: </route> ---- +== Transforming a JSon message + +For basic JSon transformation where you have a fixed structure you can represent with a combination of using +Camel simple and JSonPath language as: + +[source] +---- +{ + "company": "${jsonpath($.customer.name)}", + "location": "${jsonpath($.customer.address.country)}", + "gold": ${jsonpath($.customer.orders.length() > 5)} +} +---- + +Here we use the simple language to define the structure and use JSonPath as inlined functions via the `${jsonpath(exp)}` syntax. + +This makes it possible to use simple as a template language to define a basic structure and then JSonPath to grab the data +from an incoming JSon message. The output of the transformation is also JSon, but with simple you could +also make it XML or plain text based: + +[source,xml] +---- +<customer gold="${jsonpath($.customer.orders.length() > 5)}"> + <company>${jsonpath($.customer.name)}</company> + <location>${jsonpath($.customer.address.country)}</location> +</customer> +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSimpleTransformTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSimpleTransformTest.java new file mode 100644 index 00000000000..04fba80e077 --- /dev/null +++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSimpleTransformTest.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.jsonpath; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit5.CamelTestSupport; +import org.junit.jupiter.api.Test; + +public class JsonPathSimpleTransformTest extends CamelTestSupport { + + private static String EXPECTED = """ + { + "roll": 123, + "years": 42, + "fullname": "scott" + }"""; + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:start") + .transform().simple(""" + { + "roll": ${jsonpath($.id)}, + "years": ${jsonpath($.age)}, + "fullname": "${jsonpath($.name)}" + }""") + .to("mock:result"); + } + }; + } + + @Test + public void testTransform() throws Exception { + getMockEndpoint("mock:result").expectedBodiesReceived(EXPECTED); + + template.sendBody("direct:start", "{\"id\": 123, \"age\": 42, \"name\": \"scott\"}"); + + MockEndpoint.assertIsSatisfied(context); + } + +} diff --git a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc index 9d9452bb9b1..744273908c6 100644 --- a/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc +++ b/core/camel-core-languages/src/main/docs/modules/languages/pages/simple-language.adoc @@ -252,6 +252,9 @@ If no type is given the default is used. It is also possible to use a custom `Uu and bind the bean to the xref:manual::registry.adoc[Registry] with an id. For example `${uuid(myGenerator}` where the ID is _myGenerator_. +|jsonpath(exp) | Object | When working with JSon data, then this allows to use the JsonPath language +for example to extract data from the message body (in JSon format). This requires having camel-jsonpath JAR on the classpath. + |jq(exp) | Object | When working with JSon data, then this allows to use the JQ language for example to extract data from the message body (in JSon format). This requires having camel-jq JAR on the classpath. diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java index d0f93f30cce..2698d8fe8ce 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/ast/SimpleFunctionExpression.java @@ -462,6 +462,16 @@ public class SimpleFunctionExpression extends LiteralExpression { exp = StringHelper.removeQuotes(exp); return ExpressionBuilder.languageExpression("jq", exp); } + // jsonpath + remainder = ifStartsWithReturnRemainder("jsonpath(", function); + if (remainder != null) { + String exp = StringHelper.beforeLast(remainder, ")"); + if (exp == null) { + throw new SimpleParserException("Valid syntax: ${jsonpath(exp)} was: " + function, token.getIndex()); + } + exp = StringHelper.removeQuotes(exp); + return ExpressionBuilder.languageExpression("jsonpath", exp); + } remainder = ifStartsWithReturnRemainder("xpath(", function); if (remainder != null) { String exp = StringHelper.beforeLast(remainder, ")");