diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ObjectToJsonTransformerParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ObjectToJsonTransformerParser.java index 714845e051..4dfb716e5a 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ObjectToJsonTransformerParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ObjectToJsonTransformerParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,12 @@ package org.springframework.integration.config.xml; -import org.springframework.util.StringUtils; import org.w3c.dom.Element; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.json.ObjectToJsonTransformer; +import org.springframework.util.StringUtils; /** * @author Mark Fisher @@ -42,6 +42,10 @@ public class ObjectToJsonTransformerParser extends AbstractTransformerParser { if (StringUtils.hasText(objectMapper)) { builder.addConstructorArgReference(objectMapper); } + String resultType = element.getAttribute("result-type"); + if (StringUtils.hasText(resultType)) { + builder.addConstructorArgValue(resultType); + } if (element.hasAttribute("content-type")){ builder.addPropertyValue("contentType", element.getAttribute("content-type")); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/json/JsonToObjectTransformer.java b/spring-integration-core/src/main/java/org/springframework/integration/json/JsonToObjectTransformer.java index 778cc3a38f..28612eb1f7 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/json/JsonToObjectTransformer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/json/JsonToObjectTransformer.java @@ -23,8 +23,6 @@ import org.springframework.integration.support.json.JacksonJsonObjectMapperProvi import org.springframework.integration.support.json.JsonObjectMapper; import org.springframework.integration.transformer.AbstractTransformer; import org.springframework.messaging.Message; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; /** * Transformer implementation that converts a JSON string payload into an instance of the provided target Class. @@ -43,7 +41,7 @@ public class JsonToObjectTransformer extends AbstractTransformer implements Bean private final Class targetClass; - private final JsonObjectMapper jsonObjectMapper; + private final JsonObjectMapper jsonObjectMapper; public JsonToObjectTransformer() { this((Class) null); @@ -53,40 +51,11 @@ public class JsonToObjectTransformer extends AbstractTransformer implements Bean this(targetClass, null); } - /** - * Backward compatibility - allows existing configurations using Jackson 1.x to inject - * an ObjectMapper directly. - * - * @param targetClass The target class. - * @param objectMapper The object mapper. - * @throws ClassNotFoundException When the target class is not found. - * - * @deprecated in favor of {@link #JsonToObjectTransformer(Class, JsonObjectMapper)} - */ - @Deprecated - public JsonToObjectTransformer(Class targetClass, Object objectMapper) throws ClassNotFoundException { - this.targetClass = targetClass; - if (objectMapper != null) { - try { - Class objectMapperClass = ClassUtils.forName("org.codehaus.jackson.map.ObjectMapper", ClassUtils.getDefaultClassLoader()); - Assert.isTrue(objectMapperClass.isAssignableFrom(objectMapper.getClass())); - this.jsonObjectMapper = new org.springframework.integration.support.json.JacksonJsonObjectMapper( - (org.codehaus.jackson.map.ObjectMapper) objectMapper); - } - catch (ClassNotFoundException e) { - throw new IllegalArgumentException(e); - } - } - else { - this.jsonObjectMapper = JacksonJsonObjectMapperProvider.newInstance(); - } - } - - public JsonToObjectTransformer(JsonObjectMapper jsonObjectMapper) { + public JsonToObjectTransformer(JsonObjectMapper jsonObjectMapper) { this(null, jsonObjectMapper); } - public JsonToObjectTransformer(Class targetClass, JsonObjectMapper jsonObjectMapper) { + public JsonToObjectTransformer(Class targetClass, JsonObjectMapper jsonObjectMapper) { this.targetClass = targetClass; this.jsonObjectMapper = (jsonObjectMapper != null) ? jsonObjectMapper : JacksonJsonObjectMapperProvider.newInstance(); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/json/ObjectToJsonTransformer.java b/spring-integration-core/src/main/java/org/springframework/integration/json/ObjectToJsonTransformer.java index b9cd53c47d..fc10535582 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/json/ObjectToJsonTransformer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/json/ObjectToJsonTransformer.java @@ -22,7 +22,6 @@ import org.springframework.integration.transformer.AbstractTransformer; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.util.LinkedCaseInsensitiveMap; import org.springframework.util.StringUtils; @@ -42,43 +41,37 @@ import org.springframework.util.StringUtils; */ public class ObjectToJsonTransformer extends AbstractTransformer { + public static enum ResultType { + STRING, NODE + } + public static final String JSON_CONTENT_TYPE = "application/json"; - private final JsonObjectMapper jsonObjectMapper; + private final JsonObjectMapper jsonObjectMapper; + + private final ResultType resultType; private volatile String contentType = JSON_CONTENT_TYPE; private volatile boolean contentTypeExplicitlySet = false; - /** - * Backward compatibility - allows existing configurations using Jackson 1.x to inject - * an ObjectMapper directly. - * - * @param objectMapper The object mapper. - * - * @deprecated in favor of {@link #ObjectToJsonTransformer(JsonObjectMapper)} - */ - @Deprecated - public ObjectToJsonTransformer(Object objectMapper) { - Assert.notNull(objectMapper, "objectMapper must not be null"); - try { - Class objectMapperClass = ClassUtils.forName("org.codehaus.jackson.map.ObjectMapper", ClassUtils.getDefaultClassLoader()); - Assert.isTrue(objectMapperClass.isAssignableFrom(objectMapper.getClass())); - this.jsonObjectMapper = new org.springframework.integration.support.json.JacksonJsonObjectMapper( - (org.codehaus.jackson.map.ObjectMapper) objectMapper); - } - catch (ClassNotFoundException e) { - throw new IllegalArgumentException(e); - } - } - - public ObjectToJsonTransformer(JsonObjectMapper jsonObjectMapper) { - Assert.notNull(jsonObjectMapper, "jsonObjectMapper must not be null"); - this.jsonObjectMapper = jsonObjectMapper; - } - public ObjectToJsonTransformer() { - this.jsonObjectMapper = JacksonJsonObjectMapperProvider.newInstance(); + this(JacksonJsonObjectMapperProvider.newInstance()); + } + + public ObjectToJsonTransformer(JsonObjectMapper jsonObjectMapper) { + this(jsonObjectMapper, ResultType.STRING); + } + + public ObjectToJsonTransformer(ResultType resultType) { + this(JacksonJsonObjectMapperProvider.newInstance(), resultType); + } + + public ObjectToJsonTransformer(JsonObjectMapper jsonObjectMapper, ResultType resultType) { + Assert.notNull(jsonObjectMapper, "jsonObjectMapper must not be null"); + Assert.notNull(resultType, "'resultType' must not be null"); + this.jsonObjectMapper = jsonObjectMapper; + this.resultType = resultType; } /** @@ -95,8 +88,10 @@ public class ObjectToJsonTransformer extends AbstractTransformer { @Override protected Object doTransform(Message message) throws Exception { - String payload = this.jsonObjectMapper.toJson(message.getPayload()); - MessageBuilder messageBuilder = MessageBuilder.withPayload(payload); + Object payload = ResultType.STRING.equals(this.resultType) + ? this.jsonObjectMapper.toJson(message.getPayload()) + : this.jsonObjectMapper.toJsonNode(message.getPayload()); + MessageBuilder messageBuilder = MessageBuilder.withPayload(payload); LinkedCaseInsensitiveMap headers = new LinkedCaseInsensitiveMap(); headers.putAll(message.getHeaders()); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonMessageParser.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonMessageParser.java index becf3bf73b..d4664d83a1 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonMessageParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonMessageParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,11 +30,11 @@ import org.springframework.messaging.Message; */ abstract class AbstractJacksonJsonMessageParser

implements JsonInboundMessageMapper.JsonMessageParser

{ - private final JsonObjectMapper

objectMapper; + private final JsonObjectMapper objectMapper; private volatile JsonInboundMessageMapper messageMapper; - protected AbstractJacksonJsonMessageParser(JsonObjectMapper

objectMapper) { + protected AbstractJacksonJsonMessageParser(JsonObjectMapper objectMapper) { this.objectMapper = objectMapper; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonObjectMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonObjectMapper.java index 5f2ff9b87b..35e353c691 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonObjectMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/AbstractJacksonJsonObjectMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,10 +31,14 @@ import org.springframework.util.ClassUtils; /** * Base class for Jackson {@link JsonObjectMapper} implementations. * + * @param - The expected type of JSON Node. + * @param

- The expected type of JSON Parser. + * @param - The expected type of Java Type representation. + * * @author Artem Bilan * @since 3.0 */ -public abstract class AbstractJacksonJsonObjectMapper implements JsonObjectMapper

, BeanClassLoaderAware { +public abstract class AbstractJacksonJsonObjectMapper implements JsonObjectMapper, BeanClassLoaderAware { protected static final Collection> supportedJsonTypes = Arrays.> asList(String.class, byte[].class, File.class, URL.class, InputStream.class, Reader.class); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonObjectMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonObjectMapper.java index 30a6b28a89..40aa383d97 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonObjectMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/Jackson2JsonObjectMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2013 the original author or authors. + * Copyright 2013-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import org.springframework.util.Assert; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; /** @@ -40,7 +41,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author Artem Bilan * @since 3.0 */ -public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper { +public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper { private final ObjectMapper objectMapper; @@ -63,6 +64,11 @@ public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper T fromJson(Object json, JavaType type) throws Exception { if (json instanceof String) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonObjectMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonObjectMapper.java index 16638d6802..1b50d68cba 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonObjectMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonObjectMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import java.net.URL; import java.util.Collection; import java.util.Map; +import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.JavaType; @@ -43,7 +44,7 @@ import org.springframework.util.Assert; * @since 3.0 */ @Deprecated -public class JacksonJsonObjectMapper extends AbstractJacksonJsonObjectMapper { +public class JacksonJsonObjectMapper extends AbstractJacksonJsonObjectMapper { private final ObjectMapper objectMapper; @@ -66,6 +67,11 @@ public class JacksonJsonObjectMapper extends AbstractJacksonJsonObjectMapper T fromJson(JsonParser parser, Type valueType) throws Exception { return this.objectMapper.readValue(parser, this.constructType(valueType)); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonObjectMapperProvider.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonObjectMapperProvider.java index f5c06403f3..9cd0f6e79c 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonObjectMapperProvider.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JacksonJsonObjectMapperProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ package org.springframework.integration.support.json; public final class JacksonJsonObjectMapperProvider { @SuppressWarnings("deprecation") - public static JsonObjectMapper newInstance() { + public static JsonObjectMapper newInstance() { if (JacksonJsonUtils.isJackson2Present()) { return new Jackson2JsonObjectMapper(); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapper.java index 70b3c8c35e..3fea529b84 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2013-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,16 +23,21 @@ import java.util.Map; /** * Strategy interface to convert an Object to/from the JSON representation. * + * @param - The expected type of JSON Node. + * @param

- The expected type of JSON Parser. + * * @author Artem Bilan * @since 3.0 * */ -public interface JsonObjectMapper

{ +public interface JsonObjectMapper { String toJson(Object value) throws Exception; void toJson(Object value, Writer writer) throws Exception; + N toJsonNode(Object value) throws Exception; + T fromJson(Object json, Class valueType) throws Exception; T fromJson(Object json, Map javaTypes) throws Exception; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapperAdapter.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapperAdapter.java index e5feaeec83..eda8de1db5 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapperAdapter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonObjectMapperAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2013-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ import java.util.Map; * @author Artem Bilan * @since 3.0 */ -public abstract class JsonObjectMapperAdapter

implements JsonObjectMapper

{ +public abstract class JsonObjectMapperAdapter implements JsonObjectMapper { @Override public String toJson(Object value) throws Exception { @@ -38,6 +38,11 @@ public abstract class JsonObjectMapperAdapter

implements JsonObjectMapper

public void toJson(Object value, Writer writer) throws Exception { } + @Override + public N toJsonNode(Object value) throws Exception { + return null; + } + @Override public T fromJson(Object json, Class valueType) throws Exception { return null; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonOutboundMessageMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonOutboundMessageMapper.java index 4576dbd5f0..c9321a8501 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonOutboundMessageMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/json/JsonOutboundMessageMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,13 +32,13 @@ public class JsonOutboundMessageMapper implements OutboundMessageMapper private volatile boolean shouldExtractPayload = false; - private volatile JsonObjectMapper jsonObjectMapper; + private volatile JsonObjectMapper jsonObjectMapper; public JsonOutboundMessageMapper() { this(JacksonJsonObjectMapperProvider.newInstance()); } - public JsonOutboundMessageMapper(JsonObjectMapper jsonObjectMapper) { + public JsonOutboundMessageMapper(JsonObjectMapper jsonObjectMapper) { Assert.notNull(jsonObjectMapper, "jsonObjectMapper must not be null"); this.jsonObjectMapper = jsonObjectMapper; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/transformer/ObjectToMapTransformer.java b/spring-integration-core/src/main/java/org/springframework/integration/transformer/ObjectToMapTransformer.java index 23e9930704..5cd752fefb 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/transformer/ObjectToMapTransformer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/transformer/ObjectToMapTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,7 +54,7 @@ import org.springframework.util.StringUtils; */ public class ObjectToMapTransformer extends AbstractPayloadTransformer> { - private final JsonObjectMapper jsonObjectMapper = JacksonJsonObjectMapperProvider.newInstance(); + private final JsonObjectMapper jsonObjectMapper = JacksonJsonObjectMapperProvider.newInstance(); private volatile boolean shouldFlattenKeys = true; diff --git a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-4.0.xsd b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-4.0.xsd index 354dba7c77..e23973e8fd 100644 --- a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-4.0.xsd +++ b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-4.0.xsd @@ -2263,17 +2263,37 @@ This Jackson 1 ObjectMapper backward compatibility is deprecated and will be removed in the Spring Integration 3.1 or above. - + + + + + The type of the JSON transformation result. 'STRING' and 'NODE' values are allowed. + If 'NODE', the JSON result tree depends on the provided implementation of + 'org.springframework.integration.support.json.JsonObjectMapper' (e.g. JsonNode for + Jackson). The default value is 'STRING'. + + + + + + + + + + + + + + @@ -2310,12 +2330,11 @@ This Jackson 1 ObjectMapper backward compatibility is deprecated and will be removed in the Spring Integration 3.1 or above. - + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/json/AbstractJsonInboundMessageMapperTests.java b/spring-integration-core/src/test/java/org/springframework/integration/json/AbstractJsonInboundMessageMapperTests.java index 95e87804c4..2da2dea607 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/json/AbstractJsonInboundMessageMapperTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/json/AbstractJsonInboundMessageMapperTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,7 +48,7 @@ import org.springframework.messaging.Message; */ public abstract class AbstractJsonInboundMessageMapperTests { - private final JsonObjectMapper mapper = JacksonJsonObjectMapperProvider.newInstance(); + private final JsonObjectMapper mapper = JacksonJsonObjectMapperProvider.newInstance(); @Factory public static Matcher> sameExceptImmutableHeaders(Message operand) { diff --git a/spring-integration-core/src/test/java/org/springframework/integration/json/JsonToObjectTransformerParserTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/json/JsonToObjectTransformerParserTests-context.xml index 6df09b437e..464885f6c9 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/json/JsonToObjectTransformerParserTests-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/json/JsonToObjectTransformerParserTests-context.xml @@ -10,12 +10,6 @@ - - - - diff --git a/spring-integration-core/src/test/java/org/springframework/integration/json/JsonToObjectTransformerParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/json/JsonToObjectTransformerParserTests.java index cfc04444e8..aa162b013e 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/json/JsonToObjectTransformerParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/json/JsonToObjectTransformerParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; -import org.codehaus.jackson.JsonParser.Feature; -import org.codehaus.jackson.map.ObjectMapper; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,9 +49,6 @@ public class JsonToObjectTransformerParserTests { @Autowired private volatile MessageChannel defaultObjectMapperInput; - @Autowired - private volatile MessageChannel customObjectMapperInput; - @Autowired private volatile MessageChannel customJsonObjectMapperInput; @@ -61,19 +56,12 @@ public class JsonToObjectTransformerParserTests { @Qualifier("defaultJacksonMapperTransformer.handler") private MessageHandler defaultJacksonMapperTransformer; - @Autowired - @Qualifier("customJacksonMapperTransformer.handler") - private MessageHandler customJacksonMapperTransformer; - @Autowired @Qualifier("customJsonMapperTransformer.handler") private MessageHandler customJsonMapperTransformer; @Autowired - private ObjectMapper customObjectMapper; - - @Autowired - private JsonObjectMapper jsonObjectMapper; + private JsonObjectMapper jsonObjectMapper; @Test public void defaultObjectMapper() { @@ -95,27 +83,6 @@ public class JsonToObjectTransformerParserTests { assertEquals("123 Main Street", person.getAddress().toString()); } - @Test - public void customObjectMapper() { - Object jsonToObjectTransformer = TestUtils.getPropertyValue(this.customJacksonMapperTransformer, "transformer"); - JsonObjectMapper jsonObjectMapper = TestUtils.getPropertyValue(jsonToObjectTransformer, "jsonObjectMapper", JsonObjectMapper.class); - assertSame(this.customObjectMapper, TestUtils.getPropertyValue(jsonObjectMapper, "objectMapper")); - - String jsonString = "{firstName:'John', lastName:'Doe', age:42, address:{number:123, street:'Main Street'}}"; - QueueChannel replyChannel = new QueueChannel(); - Message message = MessageBuilder.withPayload(jsonString).setReplyChannel(replyChannel).build(); - this.customObjectMapperInput.send(message); - Message reply = replyChannel.receive(0); - assertNotNull(reply); - assertNotNull(reply.getPayload()); - assertEquals(TestPerson.class, reply.getPayload().getClass()); - TestPerson person = (TestPerson) reply.getPayload(); - assertEquals("John", person.getFirstName()); - assertEquals("Doe", person.getLastName()); - assertEquals(42, person.getAge()); - assertEquals("123 Main Street", person.getAddress().toString()); - } - @Test public void testInt2831CustomJsonObjectMapper() { Object jsonToObjectTransformer = TestUtils.getPropertyValue(this.customJsonMapperTransformer, "transformer"); @@ -133,15 +100,6 @@ public class JsonToObjectTransformerParserTests { assertEquals(jsonString, result.getJson()); } - - static class CustomObjectMapper extends ObjectMapper { - - public CustomObjectMapper() { - this.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, Boolean.TRUE); - this.configure(Feature.ALLOW_SINGLE_QUOTES, Boolean.TRUE); - } - } - @SuppressWarnings("rawtypes") static class CustomJsonObjectMapper extends JsonObjectMapperAdapter { diff --git a/spring-integration-core/src/test/java/org/springframework/integration/json/ObjectToJsonTransformerParserTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/json/ObjectToJsonTransformerParserTests-context.xml index 896373ea54..90ae2bba17 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/json/ObjectToJsonTransformerParserTests-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/json/ObjectToJsonTransformerParserTests-context.xml @@ -9,17 +9,15 @@ - - - - + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/json/ObjectToJsonTransformerParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/json/ObjectToJsonTransformerParserTests.java index 5bb4550754..b5eac1a74a 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/json/ObjectToJsonTransformerParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/json/ObjectToJsonTransformerParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,29 +19,34 @@ package org.springframework.integration.json; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.codehaus.jackson.JsonGenerator.Feature; -import org.codehaus.jackson.map.ObjectMapper; +import org.hamcrest.Matchers; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.MessageHeaders; +import org.springframework.expression.Expression; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.support.json.Jackson2JsonObjectMapper; import org.springframework.integration.support.json.JsonObjectMapperAdapter; import org.springframework.integration.test.util.TestUtils; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHeaders; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import com.fasterxml.jackson.databind.JsonNode; + /** * @author Mark Fisher * @author Oleg Zhurakousky @@ -60,10 +65,10 @@ public class ObjectToJsonTransformerParserTests { private volatile MessageChannel defaultObjectMapperInput; @Autowired - private volatile MessageChannel customObjectMapperInput; + private volatile MessageChannel customJsonObjectMapperInput; @Autowired - private volatile MessageChannel customJsonObjectMapperInput; + private volatile MessageChannel jsonNodeInput; @Test public void testContentType(){ @@ -77,10 +82,6 @@ public class ObjectToJsonTransformerParserTests { assertTrue(transformed.getHeaders().containsKey(MessageHeaders.CONTENT_TYPE)); assertEquals("application/json", transformed.getHeaders().get(MessageHeaders.CONTENT_TYPE)); - transformer = - TestUtils.getPropertyValue(context.getBean("customTransformer"), "handler.transformer", ObjectToJsonTransformer.class); - assertEquals("application/json", TestUtils.getPropertyValue(transformer, "contentType")); - transformer = TestUtils.getPropertyValue(context.getBean("emptyContentTypeTransformer"), "handler.transformer", ObjectToJsonTransformer.class); assertEquals("", TestUtils.getPropertyValue(transformer, "contentType")); @@ -127,35 +128,6 @@ public class ObjectToJsonTransformerParserTests { assertTrue(addressResult.contains("\"street\":\"Main Street\"")); } - @Test - public void customObjectMapper() { - TestAddress address = new TestAddress(); - address.setNumber(123); - address.setStreet("Main Street"); - TestPerson person = new TestPerson(); - person.setFirstName("John"); - person.setLastName("Doe"); - person.setAge(42); - person.setAddress(address); - QueueChannel replyChannel = new QueueChannel(); - Message message = MessageBuilder.withPayload(person).setReplyChannel(replyChannel).build(); - this.customObjectMapperInput.send(message); - Message reply = replyChannel.receive(0); - assertNotNull(reply); - assertNotNull(reply.getPayload()); - assertEquals(String.class, reply.getPayload().getClass()); - String resultString = (String) reply.getPayload(); - assertTrue(resultString.contains("firstName:\"John\"")); - assertTrue(resultString.contains("lastName:\"Doe\"")); - assertTrue(resultString.contains("age:42")); - Pattern addressPattern = Pattern.compile("(address:\\{.*?\\})"); - Matcher matcher = addressPattern.matcher(resultString); - assertTrue(matcher.find()); - String addressResult = matcher.group(1); - assertTrue(addressResult.contains("number:123")); - assertTrue(addressResult.contains("street:\"Main Street\"")); - } - @Test public void testInt2831CustomJsonObjectMapper() { TestPerson person = new TestPerson(); @@ -173,15 +145,27 @@ public class ObjectToJsonTransformerParserTests { assertEquals("{" + person.toString() + "}", resultString); } + @Test + public void testNodeResultType() { + TestPerson person = new TestPerson(); + person.setFirstName("John"); + person.setLastName("Doe"); + person.setAge(42); + QueueChannel replyChannel = new QueueChannel(); + Message message = MessageBuilder.withPayload(person).setReplyChannel(replyChannel).build(); + this.jsonNodeInput.send(message); + Message reply = replyChannel.receive(0); + assertNotNull(reply); + Object payload = reply.getPayload(); + assertThat(payload, Matchers.instanceOf(JsonNode.class)); + StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + evaluationContext.addPropertyAccessor(new JsonPropertyAccessor()); + Expression expression = new SpelExpressionParser().parseExpression("firstName.toString() == 'John' and age.toString() == '42'"); - static class CustomObjectMapper extends ObjectMapper { - - public CustomObjectMapper() { - this.configure(Feature.QUOTE_FIELD_NAMES, Boolean.FALSE); - } + assertTrue(expression.getValue(evaluationContext, payload, Boolean.class)); } - static class CustomJsonObjectMapper extends JsonObjectMapperAdapter { + static class CustomJsonObjectMapper extends JsonObjectMapperAdapter { @Override public String toJson(Object value) throws Exception { diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/MapJsonSerializer.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/MapJsonSerializer.java index 4832eec8fe..01b962edb9 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/MapJsonSerializer.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/MapJsonSerializer.java @@ -48,7 +48,7 @@ import org.springframework.util.Assert; */ public class MapJsonSerializer implements Serializer>, Deserializer> { - private volatile JsonObjectMapper jsonObjectMapper = JacksonJsonObjectMapperProvider.newInstance(); + private volatile JsonObjectMapper jsonObjectMapper = JacksonJsonObjectMapperProvider.newInstance(); private volatile Deserializer packetDeserializer = new ByteArrayLfSerializer(); @@ -59,7 +59,7 @@ public class MapJsonSerializer implements Serializer>, Deserializer jsonObjectMapper) { + public void setJsonObjectMapper(JsonObjectMapper jsonObjectMapper) { Assert.notNull(jsonObjectMapper, "'jsonObjectMapper' cannot be null"); this.jsonObjectMapper = jsonObjectMapper; } diff --git a/src/reference/docbook/transformer.xml b/src/reference/docbook/transformer.xml index 9caf015cc2..3a1feafb5b 100644 --- a/src/reference/docbook/transformer.xml +++ b/src/reference/docbook/transformer.xml @@ -361,13 +361,23 @@ public class Foo { In addition to JSON Transformers, Spring Integration provides a built-in #jsonPath SpEL function for use in expressions. For more information see . - + #xpath SpEL Function Since version 3.0, Spring Integration also provides a built-in #xpath SpEL function for use in expressions. For more information see . + + Beginning with version 4.0, the ObjectToJsonTransformer + supports the resultType property, to specify the node JSON representation. + The result node tree representation depends on the implementation of the provided JsonObjectMapper. + By default, the ObjectToJsonTransformer uses a Jackson2JsonObjectMapper + and delegates the conversion of the object to the node tree to the ObjectMapper#valueToTree method. + The node JSON representation provides efficiency for using the JsonPropertyAccessor, when the + downstream message flow uses SpEL expressions with access to the properties of the JSON data. See + . +
diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml index 882d6c9d67..d16fc47b1a 100644 --- a/src/reference/docbook/whats-new.xml +++ b/src/reference/docbook/whats-new.xml @@ -32,7 +32,7 @@ Migration Guide. -
+
Header Type for XPath Header Enricher The header-type attribute has been introduced for the header sub-element of the @@ -41,5 +41,14 @@ For more information see .
+
+ Object To Json Transformer: Node Result + + The result-type attribute has been introduced for the <int:object-to-json-transformer>. + This attribute provides the target type for the result of object mapping to JSON. + It supports STRING (default) and NODE. + For more information see . + +