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 8b5e11da18e4 camel-groovy - Using groovyJson can work with simple
jsonpath for basic jsonpath expressions. Add support for path from json array
object as root. (#21940)
8b5e11da18e4 is described below
commit 8b5e11da18e4e8cb1ef3b73158b9802744e9c1a0
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Mar 11 18:18:11 2026 +0100
camel-groovy - Using groovyJson can work with simple jsonpath for basic
jsonpath expressions. Add support for path from json array object as root.
(#21940)
---
.../groovy/json/GroovyJsonBulkConverterLoader.java | 126 +++++++++++++++++++++
.../services/org/apache/camel/TypeConverterLoader | 2 +
.../camel/groovy/json/GroovyJsonConverter.java | 68 +++++++++++
.../groovy/json/GroovySimpleJSonArrayOnlyTest.java | 61 ++++++++++
.../groovy/json/GroovySimpleJSonArrayTest.java | 62 ++++++++++
.../camel/groovy/json/GroovySimpleJSonTest.java | 77 +++++++++++++
.../language/simple/SimpleExpressionBuilder.java | 11 +-
.../org/apache/camel/util/json/JsonObject.java | 40 +++++--
.../apache/camel/util/json/JsonObjectPathTest.java | 29 +++++
9 files changed, 465 insertions(+), 11 deletions(-)
diff --git
a/components/camel-groovy/src/generated/java/org/apache/camel/groovy/json/GroovyJsonBulkConverterLoader.java
b/components/camel-groovy/src/generated/java/org/apache/camel/groovy/json/GroovyJsonBulkConverterLoader.java
new file mode 100644
index 000000000000..12575f79009c
--- /dev/null
+++
b/components/camel-groovy/src/generated/java/org/apache/camel/groovy/json/GroovyJsonBulkConverterLoader.java
@@ -0,0 +1,126 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.groovy.json;
+
+import javax.annotation.processing.Generated;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.DeferredContextBinding;
+import org.apache.camel.Exchange;
+import org.apache.camel.Ordered;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.TypeConverterLoaderException;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.spi.TypeConvertible;
+import org.apache.camel.spi.BulkTypeConverters;
+import org.apache.camel.spi.TypeConverterLoader;
+import org.apache.camel.spi.TypeConverterRegistry;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.TypeConverterLoaderGeneratorMojo")
+@SuppressWarnings("unchecked")
+@DeferredContextBinding
+public final class GroovyJsonBulkConverterLoader implements
TypeConverterLoader, BulkTypeConverters, CamelContextAware {
+
+ private CamelContext camelContext;
+
+ public GroovyJsonBulkConverterLoader() {
+ }
+
+ @Override
+ public void setCamelContext(CamelContext camelContext) {
+ this.camelContext = camelContext;
+ }
+
+ @Override
+ public CamelContext getCamelContext() {
+ return camelContext;
+ }
+
+ @Override
+ public int size() {
+ return 6;
+ }
+
+ @Override
+ public void load(TypeConverterRegistry registry) throws
TypeConverterLoaderException {
+ registry.addBulkTypeConverters(this);
+ doRegistration(registry);
+ }
+
+ @Override
+ public <T> T convertTo(Class<?> from, Class<T> to, Exchange exchange,
Object value) throws TypeConversionException {
+ try {
+ Object obj = doConvertTo(from, to, exchange, value);
+ return (T) obj;
+ } catch (TypeConversionException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new TypeConversionException(value, to, e);
+ }
+ }
+
+ private Object doConvertTo(Class<?> from, Class<?> to, Exchange exchange,
Object value) throws Exception {
+ if (to == org.apache.camel.util.json.JsonArray.class) {
+ if (value instanceof java.util.List) {
+ return
org.apache.camel.groovy.json.GroovyJsonConverter.convertToJsonArray((java.util.List)
value, exchange);
+ }
+ } else if (to == org.apache.camel.util.json.JsonObject.class) {
+ if (value instanceof groovy.util.Node) {
+ return
org.apache.camel.groovy.json.GroovyJsonConverter.convertToJsonObject((groovy.util.Node)
value, exchange);
+ }
+ if (value instanceof org.apache.groovy.json.internal.LazyMap) {
+ return
org.apache.camel.groovy.json.GroovyJsonConverter.convertToJsonObject((org.apache.groovy.json.internal.LazyMap)
value, exchange);
+ }
+ } else if (to == org.apache.camel.util.json.Jsonable.class) {
+ if (value instanceof groovy.util.Node) {
+ return
org.apache.camel.groovy.json.GroovyJsonConverter.convertToJson((groovy.util.Node)
value, exchange);
+ }
+ if (value instanceof org.apache.groovy.json.internal.LazyMap) {
+ return
org.apache.camel.groovy.json.GroovyJsonConverter.convertToJson((org.apache.groovy.json.internal.LazyMap)
value, exchange);
+ }
+ if (value instanceof java.util.List) {
+ return
org.apache.camel.groovy.json.GroovyJsonConverter.convertToJson((java.util.List)
value, exchange);
+ }
+ }
+ return null;
+ }
+
+ private void doRegistration(TypeConverterRegistry registry) {
+ registry.addConverter(new TypeConvertible<>(java.util.List.class,
org.apache.camel.util.json.JsonArray.class), this);
+ registry.addConverter(new TypeConvertible<>(groovy.util.Node.class,
org.apache.camel.util.json.JsonObject.class), this);
+ registry.addConverter(new
TypeConvertible<>(org.apache.groovy.json.internal.LazyMap.class,
org.apache.camel.util.json.JsonObject.class), this);
+ registry.addConverter(new TypeConvertible<>(groovy.util.Node.class,
org.apache.camel.util.json.Jsonable.class), this);
+ registry.addConverter(new
TypeConvertible<>(org.apache.groovy.json.internal.LazyMap.class,
org.apache.camel.util.json.Jsonable.class), this);
+ registry.addConverter(new TypeConvertible<>(java.util.List.class,
org.apache.camel.util.json.Jsonable.class), this);
+ }
+
+ public TypeConverter lookup(Class<?> to, Class<?> from) {
+ if (to == org.apache.camel.util.json.JsonArray.class) {
+ if (from == java.util.List.class) {
+ return this;
+ }
+ } else if (to == org.apache.camel.util.json.JsonObject.class) {
+ if (from == groovy.util.Node.class) {
+ return this;
+ }
+ if (from == org.apache.groovy.json.internal.LazyMap.class) {
+ return this;
+ }
+ } else if (to == org.apache.camel.util.json.Jsonable.class) {
+ if (from == groovy.util.Node.class) {
+ return this;
+ }
+ if (from == org.apache.groovy.json.internal.LazyMap.class) {
+ return this;
+ }
+ if (from == java.util.List.class) {
+ return this;
+ }
+ }
+ return null;
+ }
+
+}
diff --git
a/components/camel-groovy/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
b/components/camel-groovy/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
new file mode 100644
index 000000000000..3b5b6a8c4acd
--- /dev/null
+++
b/components/camel-groovy/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+org.apache.camel.groovy.json.GroovyJsonBulkConverterLoader
diff --git
a/components/camel-groovy/src/main/java/org/apache/camel/groovy/json/GroovyJsonConverter.java
b/components/camel-groovy/src/main/java/org/apache/camel/groovy/json/GroovyJsonConverter.java
new file mode 100644
index 000000000000..795d6aece289
--- /dev/null
+++
b/components/camel-groovy/src/main/java/org/apache/camel/groovy/json/GroovyJsonConverter.java
@@ -0,0 +1,68 @@
+/*
+ * 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.groovy.json;
+
+import java.util.List;
+
+import groovy.util.Node;
+import org.apache.camel.Converter;
+import org.apache.camel.Exchange;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.apache.camel.util.json.Jsonable;
+import org.apache.groovy.json.internal.LazyMap;
+
+@Converter(generateBulkLoader = true)
+public class GroovyJsonConverter {
+
+ /**
+ * Utility classes should not have a public constructor.
+ */
+ private GroovyJsonConverter() {
+ }
+
+ @Converter(order = 1)
+ public static JsonObject convertToJsonObject(Node node, Exchange exchange)
throws Exception {
+ return NodeToJsonHelper.nodeToJson(node);
+ }
+
+ @Converter(order = 2)
+ public static Jsonable convertToJson(Node node, Exchange exchange) throws
Exception {
+ return NodeToJsonHelper.nodeToJson(node);
+ }
+
+ @Converter(order = 3)
+ public static JsonObject convertToJsonObject(LazyMap node, Exchange
exchange) throws Exception {
+ return new JsonObject(node);
+ }
+
+ @Converter(order = 4)
+ public static JsonArray convertToJsonArray(List<?> node, Exchange
exchange) throws Exception {
+ return new JsonArray(node);
+ }
+
+ @Converter(order = 5)
+ public static Jsonable convertToJson(LazyMap node, Exchange exchange)
throws Exception {
+ return new JsonObject(node);
+ }
+
+ @Converter(order = 6)
+ public static Jsonable convertToJson(List<?> node, Exchange exchange)
throws Exception {
+ return new JsonArray(node);
+ }
+
+}
diff --git
a/components/camel-groovy/src/test/java/org/apache/camel/groovy/json/GroovySimpleJSonArrayOnlyTest.java
b/components/camel-groovy/src/test/java/org/apache/camel/groovy/json/GroovySimpleJSonArrayOnlyTest.java
new file mode 100644
index 000000000000..bd3dfbeb3770
--- /dev/null
+++
b/components/camel-groovy/src/test/java/org/apache/camel/groovy/json/GroovySimpleJSonArrayOnlyTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.groovy.json;
+
+import java.util.List;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class GroovySimpleJSonArrayOnlyTest extends CamelTestSupport {
+
+ private static final String ARRAY_ONLY
+ = """
+ [ "Red", "Green", "Blue" ]
+ """;
+
+ @Test
+ public void testGroovySimpleJsonPath() throws Exception {
+ getMockEndpoint("mock:result").expectedMessageCount(1);
+
getMockEndpoint("mock:result").message(0).body().isInstanceOf(List.class); //
groovy json array
+ getMockEndpoint("mock:result").expectedHeaderReceived("c1", "Red");
+ getMockEndpoint("mock:result").expectedHeaderReceived("c2", "Green");
+ getMockEndpoint("mock:result").expectedHeaderReceived("c3", "Blue");
+
+ template.sendBody("direct:start", ARRAY_ONLY);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .unmarshal().groovyJson()
+ .setHeader("c1", simple("${simpleJsonpath([0])}"))
+ .setHeader("c2", simple("${simpleJsonpath([1])}"))
+ .setHeader("c3", simple("${simpleJsonpath([2])}"))
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-groovy/src/test/java/org/apache/camel/groovy/json/GroovySimpleJSonArrayTest.java
b/components/camel-groovy/src/test/java/org/apache/camel/groovy/json/GroovySimpleJSonArrayTest.java
new file mode 100644
index 000000000000..34daf8492989
--- /dev/null
+++
b/components/camel-groovy/src/test/java/org/apache/camel/groovy/json/GroovySimpleJSonArrayTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.groovy.json;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.apache.groovy.json.internal.LazyMap;
+import org.junit.jupiter.api.Test;
+
+public class GroovySimpleJSonArrayTest extends CamelTestSupport {
+
+ private static final String COUNTRIES
+ = """
+ {
+ "countries": [ "Denmark", "Sweden", "Norway" ]
+ }
+ """;
+
+ @Test
+ public void testGroovySimpleJsonPath() throws Exception {
+ getMockEndpoint("mock:result").expectedMessageCount(1);
+
getMockEndpoint("mock:result").message(0).body().isInstanceOf(LazyMap.class);
// groovy json object
+ getMockEndpoint("mock:result").expectedHeaderReceived("c1", "Denmark");
+ getMockEndpoint("mock:result").expectedHeaderReceived("c2", "Sweden");
+ getMockEndpoint("mock:result").expectedHeaderReceived("c3", "Norway");
+
+ template.sendBody("direct:start", COUNTRIES);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .unmarshal().groovyJson()
+ .setHeader("c1",
simple("${simpleJsonpath(countries[0])}"))
+ .setHeader("c2",
simple("${simpleJsonpath(countries[1])}"))
+ .setHeader("c3",
simple("${simpleJsonpath(countries[2])}"))
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/components/camel-groovy/src/test/java/org/apache/camel/groovy/json/GroovySimpleJSonTest.java
b/components/camel-groovy/src/test/java/org/apache/camel/groovy/json/GroovySimpleJSonTest.java
new file mode 100644
index 000000000000..48f35358ad8f
--- /dev/null
+++
b/components/camel-groovy/src/test/java/org/apache/camel/groovy/json/GroovySimpleJSonTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.groovy.json;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.apache.groovy.json.internal.LazyMap;
+import org.junit.jupiter.api.Test;
+
+public class GroovySimpleJSonTest extends CamelTestSupport {
+
+ private static final String BOOKS
+ = """
+ {
+ "library": {
+ "book": [
+ {
+ "title": "No Title",
+ "author": "F. Scott Fitzgerald",
+ "year": "1925",
+ "genre": "Classic",
+ "id": "bk101"
+ },
+ {
+ "title": "1984",
+ "author": "George Orwell",
+ "year": "1949",
+ "genre": "Dystopian",
+ "id": "bk102"
+ }
+ ]
+ }
+ }
+ """;
+
+ @Test
+ public void testGroovySimpleJsonPath() throws Exception {
+ getMockEndpoint("mock:result").expectedMessageCount(1);
+
getMockEndpoint("mock:result").message(0).body().isInstanceOf(LazyMap.class);
// groovy json object
+ getMockEndpoint("mock:result").expectedHeaderReceived("title1", "No
Title");
+ getMockEndpoint("mock:result").expectedHeaderReceived("title2",
"1984");
+
+ template.sendBody("direct:start", BOOKS);
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .unmarshal().groovyJson()
+ .setHeader("title1",
simple("${simpleJsonpath(library.book[0].title)}"))
+ .setHeader("title2",
simple("${simpleJsonpath(library.book[1].title)}"))
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
index 38a2d575a9d6..81ff6c0225a7 100644
---
a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
+++
b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleExpressionBuilder.java
@@ -72,7 +72,9 @@ import org.apache.camel.util.OgnlHelper;
import org.apache.camel.util.SkipIterator;
import org.apache.camel.util.StringHelper;
import org.apache.camel.util.StringQuoteHelper;
+import org.apache.camel.util.json.JsonArray;
import org.apache.camel.util.json.JsonObject;
+import org.apache.camel.util.json.Jsonable;
/**
* Expression builder used by the simple language.
@@ -3408,9 +3410,14 @@ public final class SimpleExpressionBuilder {
@Override
public Object evaluate(Exchange exchange) {
- JsonObject jo = input.evaluate(exchange, JsonObject.class);
- if (jo != null) {
+ Jsonable j = input.evaluate(exchange, Jsonable.class);
+ if (j instanceof JsonObject jo) {
return jo.path(path);
+ } else if (j instanceof JsonArray ja) {
+ // wrap array in pseudo root to leverage json-path here
+ JsonObject jo = new JsonObject();
+ jo.put("_root_", ja);
+ return jo.path("_root_." + path);
}
return null;
}
diff --git
a/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java
b/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java
index 9cfce48e9924..d361e0b05179 100644
---
a/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java
+++
b/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java
@@ -23,6 +23,7 @@ import java.math.BigDecimal;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -146,7 +147,7 @@ public class JsonObject extends LinkedHashMap<String,
Object> implements Jsonabl
Object answer = null;
boolean optional = path.startsWith("?");
- JsonObject jo = this;
+ Map jo = this;
String sub = path;
if (optional && !path.contains(".") && !path.contains("[")) {
sub = sub.substring(1);
@@ -161,8 +162,8 @@ public class JsonObject extends LinkedHashMap<String,
Object> implements Jsonabl
java.util.Optional<Object> o = doPath(path.substring(0, pos));
if (o.isPresent()) {
answer = o.get();
- if (answer instanceof JsonObject) {
- jo = (JsonObject) answer;
+ if (answer instanceof Map) {
+ jo = (Map) answer;
}
} else {
optional = true;
@@ -173,13 +174,34 @@ public class JsonObject extends LinkedHashMap<String,
Object> implements Jsonabl
java.util.Optional<Object> o = doPath(path);
if (o.isPresent()) {
answer = o.get();
- if (answer instanceof JsonObject) {
- jo = (JsonObject) answer;
+ if (answer instanceof Map) {
+ jo = (Map) answer;
}
} else {
optional = true;
}
}
+
+ // last part can be an index
+ if (sub.startsWith("[")) {
+ int pos = -1;
+ String num = sub.substring(1, sub.length() - 1);
+ if ("last".equals(num)) {
+ pos = Integer.MAX_VALUE;
+ } else {
+ pos = Integer.parseInt(num);
+ }
+ if (pos != -1 && answer instanceof List<?> arr) {
+ jo = null;
+ if (pos == Integer.MAX_VALUE) {
+ answer = arr.getLast();
+ } else if (pos < arr.size()) {
+ answer = arr.get(pos);
+ } else {
+ answer = null;
+ }
+ }
+ }
if (jo != null) {
answer = jo.get(sub);
}
@@ -233,12 +255,12 @@ public class JsonObject extends LinkedHashMap<String,
Object> implements Jsonabl
}
part = part.substring(0, part.lastIndexOf('['));
}
- if (answer instanceof JsonObject jo) {
- answer = pos == -1 ? jo.getMap(part) : jo.getJsonArray(part);
+ if (answer instanceof Map jo) {
+ answer = jo.get(part);
} else {
- answer = pos == -1 ? getMap(part) : getJsonArray(part);
+ answer = get(part);
}
- if (pos != -1 && answer instanceof JsonArray arr) {
+ if (pos != -1 && answer instanceof List<?> arr) {
if (pos == Integer.MAX_VALUE) {
answer = arr.getLast();
} else if (pos < arr.size()) {
diff --git
a/tooling/camel-util-json/src/test/java/org/apache/camel/util/json/JsonObjectPathTest.java
b/tooling/camel-util-json/src/test/java/org/apache/camel/util/json/JsonObjectPathTest.java
index cea128dbb011..7d3498797fb9 100644
---
a/tooling/camel-util-json/src/test/java/org/apache/camel/util/json/JsonObjectPathTest.java
+++
b/tooling/camel-util-json/src/test/java/org/apache/camel/util/json/JsonObjectPathTest.java
@@ -56,6 +56,11 @@ public class JsonObjectPathTest {
}
""";
+ private static final String ARRAY_ONLY
+ = """
+ [ "Red", "Green", "Blue" ]
+ """;
+
@Test
public void testPath() throws Exception {
JsonObject jo = (JsonObject) Jsoner.deserialize(BOOKS);
@@ -172,4 +177,28 @@ public class JsonObjectPathTest {
}
}
+ @Test
+ public void testPathArrayOnly() throws Exception {
+ JsonArray jo = (JsonArray) Jsoner.deserialize(ARRAY_ONLY);
+ Assertions.assertNotNull(jo);
+ Assertions.assertEquals(3, jo.size());
+
+ // wrap in root
+ JsonObject wrap = new JsonObject();
+ wrap.put("_root_", jo);
+
+ Assertions.assertEquals("Red", wrap.path("_root_.[0]"));
+ Assertions.assertEquals("Green", wrap.path("_root_.[1]"));
+ Assertions.assertEquals("Blue", wrap.path("_root_.[2]"));
+ Assertions.assertEquals("Blue", wrap.path("_root_.[last]"));
+ Assertions.assertNull(wrap.path("_root_?.[3]"));
+ try {
+ wrap.path("_root_.[3]");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ }
+
}