This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch joc in repository https://gitbox.apache.org/repos/asf/camel.git
commit 5e448b7280f1c8e5833b5832f19442cefea17f6b Author: Claus Ibsen <[email protected]> AuthorDate: Mon Mar 9 16:41:28 2026 +0100 CAMEL-23160: camel-core - Add type converter for camel-util-json --- .../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
