You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by kl...@apache.org on 2022/05/04 10:56:22 UTC

[camel] 01/01: CAMEL-17956: use registered ObjectMapper when parsing json. Add unit tests showing use of custom ObjectMapper for both parsing and serialization.

This is an automated email from the ASF dual-hosted git repository.

klease pushed a commit to branch CAMEL-17956
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 146f770015cbb48b1bf3c6ccc5953f8ed2c919d7
Author: klease <kl...@cegetel.net>
AuthorDate: Wed May 4 12:47:41 2022 +0200

    CAMEL-17956: use registered ObjectMapper when parsing json.
    Add unit tests showing use of custom ObjectMapper for both parsing
    and serialization.
---
 .../org/apache/camel/jsonpath/JsonPathEngine.java  |  29 +++++-
 .../apache/camel/jsonpath/JsonPathExpression.java  |   2 +-
 .../apache/camel/jsonpath/CustomObjectMapper.java  |  29 ++++++
 .../camel/jsonpath/JsonPathCustomMapperTest.java   | 102 +++++++++++++++++++++
 .../SpringJsonPathCustomReadMapperBeanTest.java    |  53 +++++++++++
 .../src/test/resources/bignumbers.json             |  11 +++
 .../SpringJsonPathCustomReadMapperBeanTest.xml     |  40 ++++++++
 7 files changed, 261 insertions(+), 5 deletions(-)

diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
index 6fb4f8c8ff4..92fd05d4cd1 100644
--- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
+++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
@@ -24,14 +24,17 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.jayway.jsonpath.Configuration;
 import com.jayway.jsonpath.JsonPath;
 import com.jayway.jsonpath.Option;
 import com.jayway.jsonpath.spi.json.JacksonJsonProvider;
 import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
+import org.apache.camel.CamelContext;
 import org.apache.camel.CamelExchangeException;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
@@ -61,11 +64,11 @@ public class JsonPathEngine {
 
     @Deprecated
     public JsonPathEngine(String expression) {
-        this(expression, false, false, true, null, null);
+        this(expression, false, false, true, null, null, null);
     }
 
     public JsonPathEngine(String expression, boolean writeAsString, boolean suppressExceptions, boolean allowSimple,
-                          String headerName, Option[] options) {
+                          String headerName, Option[] options, CamelContext context) {
         this.expression = expression;
         this.writeAsString = writeAsString;
         this.headerName = headerName;
@@ -74,8 +77,16 @@ public class JsonPathEngine {
         if (options != null) {
             builder.options(options);
         }
-        builder.jsonProvider(new JacksonJsonProvider());
-        builder.mappingProvider(new JacksonMappingProvider());
+        // Use custom ObjectMapper if provided (CAMEL-17956)
+        ObjectMapper objectMapper = findRegisteredMapper(context);
+        if (objectMapper != null) {
+            builder.jsonProvider(new JacksonJsonProvider(objectMapper));
+            builder.mappingProvider(new JacksonMappingProvider(objectMapper));
+        } else {
+            builder.jsonProvider(new JacksonJsonProvider());
+            builder.mappingProvider(new JacksonMappingProvider());
+        }
+
         if (suppressExceptions) {
             builder.options(SUPPRESS_EXCEPTIONS);
         }
@@ -92,6 +103,16 @@ public class JsonPathEngine {
         this.hasSimple = simpleInUse;
     }
 
+    private ObjectMapper findRegisteredMapper(CamelContext context) {
+        if (context != null) {
+            Set<ObjectMapper> mappers = context.getRegistry().findByType(ObjectMapper.class);
+            if (mappers.size() == 1) {
+                return mappers.iterator().next();
+            }
+        }
+        return null;
+    }
+
     @SuppressWarnings("unchecked")
     public Object read(Exchange exchange) throws Exception {
         Object answer;
diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
index b40c7ce6430..c2cb7df322a 100644
--- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
+++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java
@@ -175,7 +175,7 @@ public class JsonPathExpression extends ExpressionAdapter {
 
         LOG.debug("Initializing {} using: {}", predicate ? "predicate" : "expression", exp);
         try {
-            engine = new JsonPathEngine(exp, writeAsString, suppressExceptions, allowSimple, headerName, options);
+            engine = new JsonPathEngine(exp, writeAsString, suppressExceptions, allowSimple, headerName, options, context);
         } catch (Exception e) {
             throw new ExpressionIllegalSyntaxException(exp, e);
         }
diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/CustomObjectMapper.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/CustomObjectMapper.java
new file mode 100644
index 00000000000..77dc1339bca
--- /dev/null
+++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/CustomObjectMapper.java
@@ -0,0 +1,29 @@
+/*
+ * 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 com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class CustomObjectMapper extends ObjectMapper {
+
+    public CustomObjectMapper() {
+        super();
+        this.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
+    }
+
+}
diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathCustomMapperTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathCustomMapperTest.java
new file mode 100644
index 00000000000..1b462dd36db
--- /dev/null
+++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathCustomMapperTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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 java.io.File;
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.Module;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class JsonPathCustomMapperTest extends CamelTestSupport {
+
+    static class CustomDoubleSerializer extends JsonSerializer<Double> {
+
+        @Override
+        public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+            gen.writeRawValue(String.format("%.6f", value));
+        }
+    }
+
+    static class CustomModule extends SimpleModule {
+        CustomModule() {
+            addSerializer(Double.class, new CustomDoubleSerializer());
+        }
+
+        @Override
+        public String getModuleName() {
+            return getClass().getSimpleName();
+        }
+
+        @Override
+        public int hashCode() {
+            return getClass().hashCode();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return this == o;
+        }
+    }
+
+    @Override
+    protected void bindToRegistry(Registry registry) throws Exception {
+        ObjectMapper customMapper = new ObjectMapper();
+        Module doubleModule = new CustomModule();
+        customMapper.registerModule(doubleModule);
+        registry.bind("customMapper", customMapper);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+
+                from("direct:jsonAsString")
+                        .split().jsonpathWriteAsString("$")
+                        .log("${body}")
+                        .to("mock:resultString");
+            }
+        };
+    }
+
+    @Test
+    public void testJsonPathWriteCustomDoubles() throws Exception {
+        // /CAMEL-17956
+        MockEndpoint m = getMockEndpoint("mock:resultString");
+        m.expectedMessageCount(1);
+        template.sendBody("direct:jsonAsString", new File("src/test/resources/bignumbers.json"));
+        Object resultFromMock = m.getReceivedExchanges().get(0).getMessage().getBody();
+        assertTrue(resultFromMock instanceof String);
+        assertTrue(resultFromMock.toString().contains("121002700.0"));
+        assertTrue(resultFromMock.toString().contains("-91000000.0"));
+
+    }
+
+}
diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathCustomReadMapperBeanTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathCustomReadMapperBeanTest.java
new file mode 100644
index 00000000000..7c06d521071
--- /dev/null
+++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathCustomReadMapperBeanTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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 java.io.File;
+
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class SpringJsonPathCustomReadMapperBeanTest extends CamelSpringTestSupport {
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/jsonpath/SpringJsonPathCustomReadMapperBeanTest.xml");
+    }
+
+    @Test
+    public void testJsonPathSplitNumbers() throws Exception {
+        // /CAMEL-17956
+        MockEndpoint m = getMockEndpoint("mock:result");
+        m.expectedMessageCount(1);
+        template.requestBody("direct:start", new File("src/test/resources/bignumbers.json"), String.class);
+        Object resultFromMock = m.getReceivedExchanges().get(0).getMessage().getBody();
+        //        assertTrue(resultFromMock instanceof Map);
+        //        Map<String,Object> resultMap = (Map)resultFromMock;
+        //        assertTrue(resultMap.get("principalAmountOnValueDate") instanceof BigDecimal);
+        assertTrue(resultFromMock instanceof String);
+        assertTrue(resultFromMock.toString().contains("121002700.0"));
+        assertTrue(resultFromMock.toString().contains("-91000000.0"));
+        assertMockEndpointsSatisfied();
+
+    }
+
+}
diff --git a/components/camel-jsonpath/src/test/resources/bignumbers.json b/components/camel-jsonpath/src/test/resources/bignumbers.json
new file mode 100644
index 00000000000..f055b5783f2
--- /dev/null
+++ b/components/camel-jsonpath/src/test/resources/bignumbers.json
@@ -0,0 +1,11 @@
+[
+  {
+    "adjustedRate"                     : 1.23,
+    "collateralQuantityOrNominalAmount": 987.654321,
+    "fixedRate"                        : -0.62,
+    "floatingRate"                     : 4.56,
+    "principalAmountOnMaturityDate"    : 121002700.0,
+    "principalAmountOnValueDate"       : -91000000.0,
+    "spread"                           : 4.56
+  }
+]
\ No newline at end of file
diff --git a/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathCustomReadMapperBeanTest.xml b/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathCustomReadMapperBeanTest.xml
new file mode 100644
index 00000000000..352a9b22a4f
--- /dev/null
+++ b/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathCustomReadMapperBeanTest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+            http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+  <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+      <from uri="direct:start"/>
+      <split>
+        <jsonpath writeAsString="true">$</jsonpath>
+        <to uri="log:line"/>
+        <to uri="mock:result"/>
+
+      </split>
+    </route>
+  </camelContext>
+  
+  <bean id="customMapper" class="org.apache.camel.jsonpath.CustomObjectMapper"/>
+
+</beans>
\ No newline at end of file