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
commit fdd7d9b9d8736b3e85ad9cefc1e7671c7abc9a3e Author: Claus Ibsen <[email protected]> AuthorDate: Sat Jun 4 10:05:09 2022 +0200 CAMEL-18165: camel-jackson - Add out of the box type converters for converting to/from JSonNode --- .../converter/JacksonTypeConvertersLoader.java | 30 +++++ .../src/main/docs/jackson-dataformat.adoc | 12 +- .../jackson/converter/JacksonTypeConverters.java | 72 +++++++++++ .../converter/JacksonJSonNodeConverterTest.java | 139 +++++++++++++++++++++ 4 files changed, 249 insertions(+), 4 deletions(-) diff --git a/components/camel-jackson/src/generated/java/org/apache/camel/component/jackson/converter/JacksonTypeConvertersLoader.java b/components/camel-jackson/src/generated/java/org/apache/camel/component/jackson/converter/JacksonTypeConvertersLoader.java index ec2fda53072..a527933abc1 100644 --- a/components/camel-jackson/src/generated/java/org/apache/camel/component/jackson/converter/JacksonTypeConvertersLoader.java +++ b/components/camel-jackson/src/generated/java/org/apache/camel/component/jackson/converter/JacksonTypeConvertersLoader.java @@ -37,9 +37,39 @@ public final class JacksonTypeConvertersLoader implements TypeConverterLoader, C @Override public void load(TypeConverterRegistry registry) throws TypeConverterLoaderException { + registerConverters(registry); registerFallbackConverters(registry); } + private void registerConverters(TypeConverterRegistry registry) { + addTypeConverter(registry, byte[].class, com.fasterxml.jackson.databind.JsonNode.class, false, + (type, exchange, value) -> getJacksonTypeConverters().toByteArray((com.fasterxml.jackson.databind.JsonNode) value, exchange)); + addTypeConverter(registry, com.fasterxml.jackson.databind.JsonNode.class, byte[].class, false, + (type, exchange, value) -> getJacksonTypeConverters().toJsonNode((byte[]) value, exchange)); + addTypeConverter(registry, com.fasterxml.jackson.databind.JsonNode.class, java.io.File.class, false, + (type, exchange, value) -> getJacksonTypeConverters().toJsonNode((java.io.File) value, exchange)); + addTypeConverter(registry, com.fasterxml.jackson.databind.JsonNode.class, java.io.InputStream.class, false, + (type, exchange, value) -> getJacksonTypeConverters().toJsonNode((java.io.InputStream) value, exchange)); + addTypeConverter(registry, com.fasterxml.jackson.databind.JsonNode.class, java.io.Reader.class, false, + (type, exchange, value) -> getJacksonTypeConverters().toJsonNode((java.io.Reader) value, exchange)); + addTypeConverter(registry, com.fasterxml.jackson.databind.JsonNode.class, java.lang.String.class, false, + (type, exchange, value) -> getJacksonTypeConverters().toJsonNode((java.lang.String) value, exchange)); + addTypeConverter(registry, com.fasterxml.jackson.databind.JsonNode.class, java.util.Map.class, false, + (type, exchange, value) -> getJacksonTypeConverters().toJsonNode((java.util.Map) value, exchange)); + addTypeConverter(registry, java.io.InputStream.class, com.fasterxml.jackson.databind.JsonNode.class, false, + (type, exchange, value) -> getJacksonTypeConverters().toInputStream((com.fasterxml.jackson.databind.JsonNode) value, exchange)); + addTypeConverter(registry, java.io.Reader.class, com.fasterxml.jackson.databind.JsonNode.class, false, + (type, exchange, value) -> getJacksonTypeConverters().toReader((com.fasterxml.jackson.databind.JsonNode) value, exchange)); + addTypeConverter(registry, java.lang.String.class, com.fasterxml.jackson.databind.JsonNode.class, false, + (type, exchange, value) -> getJacksonTypeConverters().toString((com.fasterxml.jackson.databind.JsonNode) value, exchange)); + addTypeConverter(registry, java.util.Map.class, com.fasterxml.jackson.databind.JsonNode.class, false, + (type, exchange, value) -> getJacksonTypeConverters().toMap((com.fasterxml.jackson.databind.JsonNode) value, exchange)); + } + + private static void addTypeConverter(TypeConverterRegistry registry, Class<?> toType, Class<?> fromType, boolean allowNull, SimpleTypeConverter.ConversionMethod method) { + registry.addTypeConverter(toType, fromType, new SimpleTypeConverter(allowNull, method)); + } + private void registerFallbackConverters(TypeConverterRegistry registry) { addFallbackTypeConverter(registry, false, false, (type, exchange, value) -> getJacksonTypeConverters().convertTo(type, exchange, value, registry)); } diff --git a/components/camel-jackson/src/main/docs/jackson-dataformat.adoc b/components/camel-jackson/src/main/docs/jackson-dataformat.adoc index b4098f20959..0f96603425d 100644 --- a/components/camel-jackson/src/main/docs/jackson-dataformat.adoc +++ b/components/camel-jackson/src/main/docs/jackson-dataformat.adoc @@ -40,14 +40,18 @@ and then use it. When this happens you should set a `INFO` logging from Camel. == Using Jackson for automatic type conversion The `camel-jackson` module allows integrating Jackson as a xref:manual::type-converter.adoc[Type Converter]. -This works in similar ways that xref:dataformats:jaxb-dataformat.adoc[JAXB] integrates with Camels type converter. -To use this `camel-jackson` must be enabled, which is done by setting the following options -on the `CamelContext` global options, as shown: +This gives a set of out of the box converters to/from the Jackson type `JSonNode`, such as converting +from `JSonNode` to `String` or vice-versa. + +=== Enabling more type converters and support for POJOs + +To enable POJO conversion support for `camel-jackson` then this must be enabled, +which is done by setting the following options on the `CamelContext` global options, as shown: [source,java] ---- -// Enable Jackson JSON type converter. +// Enable Jackson JSON type converter for more types. camelContext.getGlobalOptions().put("CamelJacksonEnableTypeConverter", "true"); // Allow Jackson JSON to convert to pojo types also // (by default Jackson only converts to String and other simple types) diff --git a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/converter/JacksonTypeConverters.java b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/converter/JacksonTypeConverters.java index 0751d2c110e..20830dc5986 100644 --- a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/converter/JacksonTypeConverters.java +++ b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/converter/JacksonTypeConverters.java @@ -16,13 +16,17 @@ */ package org.apache.camel.component.jackson.converter; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.Reader; import java.nio.ByteBuffer; import java.util.Map; import java.util.Set; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.Module; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.camel.CamelContext; @@ -61,6 +65,74 @@ public final class JacksonTypeConverters { this.lock = new Object(); } + @Converter + public JsonNode toJsonNode(String text, Exchange exchange) throws Exception { + ObjectMapper mapper = resolveObjectMapper(exchange.getContext()); + return mapper.readTree(text); + } + + @Converter + public JsonNode toJsonNode(byte[] arr, Exchange exchange) throws Exception { + ObjectMapper mapper = resolveObjectMapper(exchange.getContext()); + return mapper.readTree(arr); + } + + @Converter + public JsonNode toJsonNode(InputStream is, Exchange exchange) throws Exception { + ObjectMapper mapper = resolveObjectMapper(exchange.getContext()); + return mapper.readTree(is); + } + + @Converter + public JsonNode toJsonNode(File file, Exchange exchange) throws Exception { + ObjectMapper mapper = resolveObjectMapper(exchange.getContext()); + return mapper.readTree(file); + } + + @Converter + public JsonNode toJsonNode(Reader reader, Exchange exchange) throws Exception { + ObjectMapper mapper = resolveObjectMapper(exchange.getContext()); + return mapper.readTree(reader); + } + + @Converter + public JsonNode toJsonNode(Map map, Exchange exchange) throws Exception { + ObjectMapper mapper = resolveObjectMapper(exchange.getContext()); + return mapper.valueToTree(map); + } + + @Converter + public String toString(JsonNode node, Exchange exchange) throws Exception { + ObjectMapper mapper = resolveObjectMapper(exchange.getContext()); + // output as string in pretty mode + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node); + } + + @Converter + public byte[] toByteArray(JsonNode node, Exchange exchange) throws Exception { + ObjectMapper mapper = resolveObjectMapper(exchange.getContext()); + return mapper.writeValueAsBytes(node); + } + + @Converter + public InputStream toInputStream(JsonNode node, Exchange exchange) throws Exception { + byte[] arr = toByteArray(node, exchange); + return new ByteArrayInputStream(arr); + } + + @Converter + public Map<String, Object> toMap(JsonNode node, Exchange exchange) throws Exception { + ObjectMapper mapper = resolveObjectMapper(exchange.getContext()); + return mapper.convertValue(node, new TypeReference<Map<String, Object>>() { + }); + } + + @Converter + public Reader toReader(JsonNode node, Exchange exchange) throws Exception { + InputStream is = toInputStream(node, exchange); + return new InputStreamReader(is); + } + @Converter(fallback = true) public <T> T convertTo(Class<T> type, Exchange exchange, Object value, TypeConverterRegistry registry) throws Exception { diff --git a/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/converter/JacksonJSonNodeConverterTest.java b/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/converter/JacksonJSonNodeConverterTest.java new file mode 100644 index 00000000000..a34300ea244 --- /dev/null +++ b/components/camel-jackson/src/test/java/org/apache/camel/component/jackson/converter/JacksonJSonNodeConverterTest.java @@ -0,0 +1,139 @@ +/* + * 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.component.jackson.converter; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.camel.Exchange; +import org.apache.camel.support.DefaultExchange; +import org.apache.camel.test.junit5.CamelTestSupport; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class JacksonJSonNodeConverterTest extends CamelTestSupport { + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + @Test + public void stringToJsonNode() { + Exchange exchange = new DefaultExchange(context); + + JsonNode node = context.getTypeConverter().convertTo(JsonNode.class, exchange, "{ \"message\": \"Hello World\" }"); + assertNotNull(node); + + Assertions.assertEquals("\"Hello World\"", node.get("message").toString()); + } + + @Test + public void byteArrayToJsonNode() { + Exchange exchange = new DefaultExchange(context); + + JsonNode node = context.getTypeConverter().convertTo(JsonNode.class, exchange, + "{ \"message\": \"Bye World\" }".getBytes(StandardCharsets.UTF_8)); + assertNotNull(node); + + Assertions.assertEquals("\"Bye World\"", node.get("message").toString()); + } + + @Test + public void inputStreamToJsonNode() { + Exchange exchange = new DefaultExchange(context); + + ByteArrayInputStream bis = new ByteArrayInputStream("{ \"message\": \"Bye World\" }".getBytes(StandardCharsets.UTF_8)); + JsonNode node = context.getTypeConverter().convertTo(JsonNode.class, exchange, bis); + assertNotNull(node); + + Assertions.assertEquals("\"Bye World\"", node.get("message").toString()); + } + + @Test + public void mapToJsonNode() { + Exchange exchange = new DefaultExchange(context); + + Map<String, Object> map = Map.of("message", "Hello Camel"); + JsonNode node = context.getTypeConverter().convertTo(JsonNode.class, exchange, map); + assertNotNull(node); + + Assertions.assertEquals("\"Hello Camel\"", node.get("message").toString()); + } + + @Test + public void jsonNodeToString() { + Exchange exchange = new DefaultExchange(context); + + Map<String, Object> map = Map.of("message", "Hello Camel"); + JsonNode node = context.getTypeConverter().convertTo(JsonNode.class, exchange, map); + + String text = context.getTypeConverter().convertTo(String.class, exchange, node); + assertNotNull(text); + + Assertions.assertEquals("{\n \"message\" : \"Hello Camel\"\n}", text); + } + + @Test + public void jsonNodeToByteArray() { + Exchange exchange = new DefaultExchange(context); + + Map<String, Object> map = Map.of("message", "Hello Camel"); + JsonNode node = context.getTypeConverter().convertTo(JsonNode.class, exchange, map); + + byte[] arr = context.getTypeConverter().convertTo(byte[].class, exchange, node); + assertNotNull(arr); + String s = context.getTypeConverter().convertTo(String.class, exchange, arr); + + Assertions.assertEquals("{\"message\":\"Hello Camel\"}", s); + } + + @Test + public void jsonNodeToInputStream() { + Exchange exchange = new DefaultExchange(context); + + Map<String, Object> map = Map.of("message", "Hello Camel"); + JsonNode node = context.getTypeConverter().convertTo(JsonNode.class, exchange, map); + + InputStream is = context.getTypeConverter().convertTo(InputStream.class, exchange, node); + assertNotNull(is); + String s = context.getTypeConverter().convertTo(String.class, exchange, is); + + Assertions.assertEquals("{\"message\":\"Hello Camel\"}", s); + } + + @Test + public void jsonNodeToMap() { + Exchange exchange = new DefaultExchange(context); + + Map<String, Object> map = Map.of("message", "Bye Camel", "age", 44); + JsonNode node = context.getTypeConverter().convertTo(JsonNode.class, exchange, map); + + Map out = context.getTypeConverter().convertTo(Map.class, exchange, node); + assertNotNull(out); + + Assertions.assertEquals(2, out.size()); + Assertions.assertEquals("Bye Camel", out.get("message")); + Assertions.assertEquals(44, out.get("age")); + } + +}
