You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/11/26 12:26:17 UTC

(camel) 05/05: CAMEL-20154: camel-jsonpath - Make it easier to grab elements in a template like fashion

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 <cl...@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, ")");