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 f429cbb3035c CAMEL-23160: camel-core - Add type converter for
camel-util-json (#21879)
f429cbb3035c is described below
commit f429cbb3035c1faf4331730571993dcd551d3bfd
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Mar 10 07:33:28 2026 +0100
CAMEL-23160: camel-core - Add type converter for camel-util-json (#21879)
---
.../camel/converter/json/JsonConverterTest.java | 99 ++++++++++++++
.../stream/CamelSupportBulkConverterLoader.java | 144 +++++++++++++++++++++
.../services/org/apache/camel/TypeConverterLoader | 2 +-
.../apache/camel/converter/json/JsonConverter.java | 47 +++++++
.../java/org/apache/camel/util/json/JsonArray.java | 22 ++++
.../org/apache/camel/util/json/JsonObject.java | 22 ++++
6 files changed, 335 insertions(+), 1 deletion(-)
diff --git
a/core/camel-core/src/test/java/org/apache/camel/converter/json/JsonConverterTest.java
b/core/camel-core/src/test/java/org/apache/camel/converter/json/JsonConverterTest.java
new file mode 100644
index 000000000000..6bc743e268b9
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/converter/json/JsonConverterTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.converter.json;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class JsonConverterTest extends ContextTestSupport {
+
+ 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"
+ }
+ ]
+ }
+ }
+ """;
+
+ private static final String BOOKS_ARR = """
+ [
+ {
+ "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 testConvertObject() throws Exception {
+ JsonObject jo = context.getTypeConverter().convertTo(JsonObject.class,
BOOKS);
+ Assertions.assertNotNull(jo);
+
+ JsonArray arr = jo.getJsonObject("library").getJsonArray("book");
+ Assertions.assertEquals(2, arr.size());
+ JsonObject b1 = arr.getJsonObject(0);
+ JsonObject b2 = arr.getJsonObject(1);
+ Assertions.assertEquals("No Title", b1.getString("title"));
+ Assertions.assertEquals(1925, b1.getInteger("year"));
+ Assertions.assertEquals("1984", b2.getString("title"));
+ Assertions.assertEquals(1949, b2.getInteger("year"));
+ }
+
+ @Test
+ public void testConvertArray() throws Exception {
+ JsonArray arr = context.getTypeConverter().convertTo(JsonArray.class,
BOOKS_ARR);
+ Assertions.assertNotNull(arr);
+
+ Assertions.assertEquals(2, arr.size());
+ JsonObject b1 = arr.getJsonObject(0);
+ JsonObject b2 = arr.getJsonObject(1);
+ Assertions.assertEquals("No Title", b1.getString("title"));
+ Assertions.assertEquals(1925, b1.getInteger("year"));
+ Assertions.assertEquals("1984", b2.getString("title"));
+ Assertions.assertEquals(1949, b2.getInteger("year"));
+ }
+
+}
diff --git
a/core/camel-support/src/generated/java/org/apache/camel/converter/stream/CamelSupportBulkConverterLoader.java
b/core/camel-support/src/generated/java/org/apache/camel/converter/stream/CamelSupportBulkConverterLoader.java
new file mode 100644
index 000000000000..7a7a1177fc87
--- /dev/null
+++
b/core/camel-support/src/generated/java/org/apache/camel/converter/stream/CamelSupportBulkConverterLoader.java
@@ -0,0 +1,144 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.converter.stream;
+
+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 CamelSupportBulkConverterLoader implements
TypeConverterLoader, BulkTypeConverters, CamelContextAware {
+
+ private CamelContext camelContext;
+
+ public CamelSupportBulkConverterLoader() {
+ }
+
+ @Override
+ public void setCamelContext(CamelContext camelContext) {
+ this.camelContext = camelContext;
+ }
+
+ @Override
+ public CamelContext getCamelContext() {
+ return camelContext;
+ }
+
+ @Override
+ public int size() {
+ return 8;
+ }
+
+ @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 == byte[].class) {
+ if (value instanceof org.apache.camel.StreamCache) {
+ return
org.apache.camel.converter.stream.StreamCacheConverter.convertToByteArray((org.apache.camel.StreamCache)
value, exchange);
+ }
+ } else if (to == java.nio.ByteBuffer.class) {
+ if (value instanceof org.apache.camel.StreamCache) {
+ return
org.apache.camel.converter.stream.StreamCacheConverter.convertToByteBuffer((org.apache.camel.StreamCache)
value, exchange);
+ }
+ } else if (to == org.apache.camel.StreamCache.class) {
+ if (value instanceof java.io.ByteArrayInputStream) {
+ return
org.apache.camel.converter.stream.StreamCacheConverter.convertToStreamCache((java.io.ByteArrayInputStream)
value, exchange);
+ }
+ if (value instanceof java.io.InputStream) {
+ return
org.apache.camel.converter.stream.StreamCacheConverter.convertToStreamCache((java.io.InputStream)
value, exchange);
+ }
+ if (value instanceof
org.apache.camel.converter.stream.CachedOutputStream) {
+ return
org.apache.camel.converter.stream.StreamCacheConverter.convertToStreamCache((org.apache.camel.converter.stream.CachedOutputStream)
value, exchange);
+ }
+ if (value instanceof java.io.Reader) {
+ return
org.apache.camel.converter.stream.StreamCacheConverter.convertToStreamCache((java.io.Reader)
value, exchange);
+ }
+ } else if (to == org.apache.camel.util.json.JsonArray.class) {
+ if (value instanceof java.lang.String) {
+ return
org.apache.camel.converter.json.JsonConverter.convertToJsonArray((java.lang.String)
value, exchange);
+ }
+ } else if (to == org.apache.camel.util.json.JsonObject.class) {
+ if (value instanceof java.lang.String) {
+ return
org.apache.camel.converter.json.JsonConverter.convertToJsonObject((java.lang.String)
value, exchange);
+ }
+ }
+ return null;
+ }
+
+ private void doRegistration(TypeConverterRegistry registry) {
+ registry.addConverter(new
TypeConvertible<>(org.apache.camel.StreamCache.class, byte[].class), this);
+ registry.addConverter(new
TypeConvertible<>(org.apache.camel.StreamCache.class,
java.nio.ByteBuffer.class), this);
+ registry.addConverter(new
TypeConvertible<>(java.io.ByteArrayInputStream.class,
org.apache.camel.StreamCache.class), this);
+ registry.addConverter(new TypeConvertible<>(java.io.InputStream.class,
org.apache.camel.StreamCache.class), this);
+ registry.addConverter(new
TypeConvertible<>(org.apache.camel.converter.stream.CachedOutputStream.class,
org.apache.camel.StreamCache.class), this);
+ registry.addConverter(new TypeConvertible<>(java.io.Reader.class,
org.apache.camel.StreamCache.class), this);
+ registry.addConverter(new TypeConvertible<>(java.lang.String.class,
org.apache.camel.util.json.JsonArray.class), this);
+ registry.addConverter(new TypeConvertible<>(java.lang.String.class,
org.apache.camel.util.json.JsonObject.class), this);
+ }
+
+ public TypeConverter lookup(Class<?> to, Class<?> from) {
+ if (to == byte[].class) {
+ if (from == org.apache.camel.StreamCache.class) {
+ return this;
+ }
+ } else if (to == java.nio.ByteBuffer.class) {
+ if (from == org.apache.camel.StreamCache.class) {
+ return this;
+ }
+ } else if (to == org.apache.camel.StreamCache.class) {
+ if (from == java.io.ByteArrayInputStream.class) {
+ return this;
+ }
+ if (from == java.io.InputStream.class) {
+ return this;
+ }
+ if (from ==
org.apache.camel.converter.stream.CachedOutputStream.class) {
+ return this;
+ }
+ if (from == java.io.Reader.class) {
+ return this;
+ }
+ } else if (to == org.apache.camel.util.json.JsonArray.class) {
+ if (from == java.lang.String.class) {
+ return this;
+ }
+ } else if (to == org.apache.camel.util.json.JsonObject.class) {
+ if (from == java.lang.String.class) {
+ return this;
+ }
+ }
+ return null;
+ }
+
+}
diff --git
a/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
b/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
index 67c03404364e..1ef7881f482d 100644
---
a/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
+++
b/core/camel-support/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
@@ -1,2 +1,2 @@
# Generated by camel build tools - do NOT edit this file!
-org.apache.camel.converter.stream.StreamCacheBulkConverterLoader
+org.apache.camel.converter.stream.CamelSupportBulkConverterLoader
diff --git
a/core/camel-support/src/main/java/org/apache/camel/converter/json/JsonConverter.java
b/core/camel-support/src/main/java/org/apache/camel/converter/json/JsonConverter.java
new file mode 100644
index 000000000000..15b4d75cd1f3
--- /dev/null
+++
b/core/camel-support/src/main/java/org/apache/camel/converter/json/JsonConverter.java
@@ -0,0 +1,47 @@
+/*
+ * 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.converter.json;
+
+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.Jsoner;
+
+/**
+ * A set of {@link Converter} methods for camel-util-json objects.
+ */
+@Converter(generateBulkLoader = true)
+public final class JsonConverter {
+
+ /**
+ * Utility classes should not have a public constructor.
+ */
+ private JsonConverter() {
+ }
+
+ @Converter(order = 1)
+ public static JsonObject convertToJsonObject(String json, Exchange
exchange) throws Exception {
+ return Jsoner.deserialize(json, (JsonObject) null);
+ }
+
+ @Converter(order = 2)
+ public static JsonArray convertToJsonArray(String json, Exchange exchange)
throws Exception {
+ return (JsonArray) Jsoner.deserialize(json);
+ }
+
+}
diff --git
a/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonArray.java
b/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonArray.java
index fadc301de0fa..fa1ed51f1f95 100644
---
a/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonArray.java
+++
b/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonArray.java
@@ -71,6 +71,28 @@ public class JsonArray extends ArrayList<Object> implements
Jsonable {
}
}
+ /**
+ * A convenience method that assumes there is another JsonObject at the
given index.
+ *
+ * @param index representing where the value is expected to
be at.
+ * @return the value stored at the key.
+ * @throws ClassCastException if the value didn't match the assumed return
type.
+ */
+ public JsonObject getJsonObject(final int index) {
+ return getMap(index);
+ }
+
+ /**
+ * A convenience method that assumes there is a JsonArray at the given
index.
+ *
+ * @param index representing where the value is expected to
be at.
+ * @return the value stored at the key.
+ * @throws ClassCastException if the value didn't match the assumed return
type.
+ */
+ public JsonArray getJsonArray(final int index) {
+ return getCollection(index);
+ }
+
/**
* A convenience method that assumes there is a BigDecimal, Number, or
String at the given index. If a Number or
* String is there it is used to construct a new BigDecimal.
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 13354f2c87ad..e3c93873a2be 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
@@ -55,6 +55,28 @@ public class JsonObject extends LinkedHashMap<String,
Object> implements Jsonabl
super(map);
}
+ /**
+ * A convenience method that assumes there is another JsonObject at the
given key.
+ *
+ * @param key representing where the value ought to be
stored at.
+ * @return the value stored at the key.
+ * @throws ClassCastException if the value didn't match the assumed return
type.
+ */
+ public JsonObject getJsonObject(final String key) {
+ return getMap(key);
+ }
+
+ /**
+ * A convenience method that assumes there is a JsonArray at the given key.
+ *
+ * @param key representing where the value ought to be
stored at.
+ * @return the value stored at the key.
+ * @throws ClassCastException if the value didn't match the assumed return
type.
+ */
+ public JsonArray getJsonArray(final String key) {
+ return getCollection(key);
+ }
+
/**
* A convenience method that assumes there is a BigDecimal, Number, or
String at the given key. If a Number is there
* its Number#toString() is used to construct a new BigDecimal(String). If
a String is there it is used to construct