INT-3370: Add BoonJsonObjectMapper
JIRA: https://jira.spring.io/browse/INT-3370 * Add `BoonJsonObjectMapper` * Provide some tests * Remove deprecations * Polishing test according removed deprecations * Change `JsonObjectMapper#populateJavaTypes` to get deal with `payload`, not its `class`, since we can't (and Jackson's `TypeFactory`, too) determine generic type from `Collection`. Use `iterators` instead to retrieve the type from the first item. Conflicts: build.gradle spring-integration-amqp/src/test/java/org/springframework/integration/amqp/support/DefaultAmqpHeaderMapperTests.java INT-3370: Polishing according PR comments * Apply Gary's polishing to the Docs * Fix `RecipientListRouter` JavaDoc warn * Fix typo in test name for `UdpUnicastEndToEndTests` * Fix `RedisQueueOutboundChannelAdapterTests` do not use Jackson 1.x Final Polish
This commit is contained in:
committed by
Gary Russell
parent
cda4a99023
commit
f84e798272
@@ -70,6 +70,7 @@ subprojects { subproject ->
|
||||
activeMqVersion = '5.9.0'
|
||||
aspectjVersion = '1.8.0'
|
||||
apacheSshdVersion = '0.10.1'
|
||||
boonVersion = '0.22'
|
||||
commonsDbcpVersion = '1.4'
|
||||
commonsIoVersion = '2.4'
|
||||
commonsNetVersion = '3.3'
|
||||
@@ -83,7 +84,6 @@ subprojects { subproject ->
|
||||
hibernateVersion = '4.2.11.Final'
|
||||
hsqldbVersion = '2.3.2'
|
||||
h2Version = '1.3.175'
|
||||
jacksonVersion = '1.9.13'
|
||||
jackson2Version = '2.3.2'
|
||||
javaxActivationVersion = '1.1.1'
|
||||
javaxMailVersion = '1.4.7'
|
||||
@@ -246,9 +246,9 @@ project('spring-integration-core') {
|
||||
compile "org.springframework.retry:spring-retry:$springRetryVersion"
|
||||
compile "org.projectreactor:reactor-core:$reactorVersion"
|
||||
compile("org.projectreactor.spring:reactor-spring-context:$reactorSpringVersion", optional)
|
||||
compile("org.codehaus.jackson:jackson-mapper-asl:$jacksonVersion", optional)
|
||||
compile("com.fasterxml.jackson.core:jackson-databind:$jackson2Version", optional)
|
||||
compile("com.jayway.jsonpath:json-path:$jsonpathVersion", optional)
|
||||
compile("io.fastjson:boon:$boonVersion", optional)
|
||||
|
||||
testCompile ("org.aspectj:aspectjweaver:$aspectjVersion")
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.rabbitmq.client.Channel;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
@@ -41,7 +42,7 @@ import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
||||
import org.springframework.amqp.rabbit.support.CorrelationData;
|
||||
import org.springframework.amqp.support.converter.JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.SimpleMessageConverter;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
@@ -60,8 +61,6 @@ import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
import com.rabbitmq.client.Channel;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
@@ -85,7 +84,7 @@ public class InboundEndpointTests {
|
||||
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
|
||||
|
||||
AmqpInboundChannelAdapter adapter = new AmqpInboundChannelAdapter(container);
|
||||
adapter.setMessageConverter(new JsonMessageConverter());
|
||||
adapter.setMessageConverter(new Jackson2JsonMessageConverter());
|
||||
|
||||
PollableChannel channel = new QueueChannel();
|
||||
|
||||
@@ -140,7 +139,8 @@ public class InboundEndpointTests {
|
||||
Object payload = new Foo("bar1");
|
||||
|
||||
MessageProperties amqpMessageProperties = new MessageProperties();
|
||||
org.springframework.amqp.core.Message amqpMessage = new JsonMessageConverter().toMessage(payload, amqpMessageProperties);
|
||||
org.springframework.amqp.core.Message amqpMessage =
|
||||
new Jackson2JsonMessageConverter().toMessage(payload, amqpMessageProperties);
|
||||
|
||||
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
|
||||
listener.onMessage(amqpMessage, null);
|
||||
@@ -186,20 +186,22 @@ public class InboundEndpointTests {
|
||||
}));
|
||||
|
||||
AmqpInboundGateway gateway = new AmqpInboundGateway(container);
|
||||
gateway.setMessageConverter(new JsonMessageConverter());
|
||||
gateway.setMessageConverter(new Jackson2JsonMessageConverter());
|
||||
|
||||
gateway.setRequestChannel(channel);
|
||||
gateway.setBeanFactory(mock(BeanFactory.class));
|
||||
gateway.afterPropertiesSet();
|
||||
|
||||
RabbitTemplate rabbitTemplate = Mockito.spy(TestUtils.getPropertyValue(gateway, "amqpTemplate", RabbitTemplate.class));
|
||||
RabbitTemplate rabbitTemplate = Mockito.spy(TestUtils.getPropertyValue(gateway, "amqpTemplate",
|
||||
RabbitTemplate.class));
|
||||
|
||||
Mockito.doAnswer(new Answer<Object>() {
|
||||
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
org.springframework.amqp.core.Message message = (org.springframework.amqp.core.Message) invocation.getArguments()[2];
|
||||
Map<String,Object> headers = message.getMessageProperties().getHeaders();
|
||||
org.springframework.amqp.core.Message message =
|
||||
(org.springframework.amqp.core.Message) invocation.getArguments()[2];
|
||||
Map<String, Object> headers = message.getMessageProperties().getHeaders();
|
||||
assertTrue(headers.containsKey(JsonHeaders.TYPE_ID.replaceFirst(JsonHeaders.PREFIX, "")));
|
||||
assertNotEquals("foo", headers.get(JsonHeaders.TYPE_ID.replaceFirst(JsonHeaders.PREFIX, "")));
|
||||
assertFalse(headers.containsKey(JsonHeaders.CONTENT_TYPE_ID.replaceFirst(JsonHeaders.PREFIX, "")));
|
||||
@@ -209,9 +211,7 @@ public class InboundEndpointTests {
|
||||
assertFalse(headers.containsKey(JsonHeaders.CONTENT_TYPE_ID));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
).when(rabbitTemplate).send(Mockito.anyString(), Mockito.anyString(),
|
||||
}).when(rabbitTemplate).send(Mockito.anyString(), Mockito.anyString(),
|
||||
Mockito.any(org.springframework.amqp.core.Message.class), Mockito.any(CorrelationData.class));
|
||||
|
||||
DirectFieldAccessor directFieldAccessor = new DirectFieldAccessor(gateway);
|
||||
@@ -222,7 +222,8 @@ public class InboundEndpointTests {
|
||||
MessageProperties amqpMessageProperties = new MessageProperties();
|
||||
amqpMessageProperties.setReplyTo("test");
|
||||
amqpMessageProperties.setDeliveryTag(123L);
|
||||
org.springframework.amqp.core.Message amqpMessage = new JsonMessageConverter().toMessage(payload, amqpMessageProperties);
|
||||
org.springframework.amqp.core.Message amqpMessage =
|
||||
new Jackson2JsonMessageConverter().toMessage(payload, amqpMessageProperties);
|
||||
|
||||
ChannelAwareMessageListener listener = (ChannelAwareMessageListener) container.getMessageListener();
|
||||
listener.onMessage(amqpMessage, rabbitChannel);
|
||||
@@ -230,7 +231,6 @@ public class InboundEndpointTests {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class Foo {
|
||||
|
||||
private String bar;
|
||||
@@ -257,11 +257,8 @@ public class InboundEndpointTests {
|
||||
|
||||
Foo foo = (Foo) o;
|
||||
|
||||
if (bar != null ? !bar.equals(foo.bar) : foo.bar != null) {
|
||||
return false;
|
||||
}
|
||||
return !(bar != null ? !bar.equals(foo.bar) : foo.bar != null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,14 +27,16 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageDeliveryMode;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.support.converter.JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.integration.amqp.AmqpHeaders;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
@@ -198,7 +200,7 @@ public class DefaultAmqpHeaderMapperTests {
|
||||
@Test // INT-2090
|
||||
public void jsonTypeIdNotOverwritten() {
|
||||
DefaultAmqpHeaderMapper headerMapper = new DefaultAmqpHeaderMapper();
|
||||
JsonMessageConverter converter = new JsonMessageConverter();
|
||||
MessageConverter converter = new Jackson2JsonMessageConverter();
|
||||
MessageProperties amqpProperties = new MessageProperties();
|
||||
converter.toMessage("123", amqpProperties);
|
||||
Map<String, Object> headerMap = new HashMap<String, Object>();
|
||||
|
||||
@@ -19,14 +19,14 @@ package org.springframework.integration.json;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.integration.mapping.support.JsonHeaders;
|
||||
import org.springframework.integration.support.AbstractIntegrationMessageBuilder;
|
||||
import org.springframework.integration.support.json.JacksonJsonObjectMapperProvider;
|
||||
import org.springframework.integration.support.json.JsonObjectMapperProvider;
|
||||
import org.springframework.integration.support.json.JsonObjectMapper;
|
||||
import org.springframework.integration.transformer.AbstractTransformer;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
/**
|
||||
* Transformer implementation that converts a JSON string payload into an instance of the provided target Class.
|
||||
* By default this transformer uses {@linkplain JacksonJsonObjectMapperProvider} factory
|
||||
* By default this transformer uses {@linkplain org.springframework.integration.support.json.JsonObjectMapperProvider} factory
|
||||
* to get an instance of Jackson 1 or Jackson 2 JSON-processor {@linkplain JsonObjectMapper} implementation
|
||||
* depending on the jackson-databind or jackson-mapper-asl libs on the classpath.
|
||||
* Any other {@linkplain JsonObjectMapper} implementation can be provided.
|
||||
@@ -34,7 +34,7 @@ import org.springframework.messaging.Message;
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
* @see JsonObjectMapper
|
||||
* @see JacksonJsonObjectMapperProvider
|
||||
* @see org.springframework.integration.support.json.JsonObjectMapperProvider
|
||||
* @since 2.0
|
||||
*/
|
||||
public class JsonToObjectTransformer extends AbstractTransformer implements BeanClassLoaderAware {
|
||||
@@ -57,7 +57,7 @@ public class JsonToObjectTransformer extends AbstractTransformer implements Bean
|
||||
|
||||
public JsonToObjectTransformer(Class<?> targetClass, JsonObjectMapper<?, ?> jsonObjectMapper) {
|
||||
this.targetClass = targetClass;
|
||||
this.jsonObjectMapper = (jsonObjectMapper != null) ? jsonObjectMapper : JacksonJsonObjectMapperProvider.newInstance();
|
||||
this.jsonObjectMapper = (jsonObjectMapper != null) ? jsonObjectMapper : JsonObjectMapperProvider.newInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package org.springframework.integration.json;
|
||||
|
||||
import org.springframework.integration.support.AbstractIntegrationMessageBuilder;
|
||||
import org.springframework.integration.support.json.JacksonJsonObjectMapperProvider;
|
||||
import org.springframework.integration.support.json.JsonObjectMapperProvider;
|
||||
import org.springframework.integration.support.json.JsonObjectMapper;
|
||||
import org.springframework.integration.transformer.AbstractTransformer;
|
||||
import org.springframework.messaging.Message;
|
||||
@@ -27,7 +27,7 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Transformer implementation that converts a payload instance into a JSON string representation.
|
||||
* By default this transformer uses {@linkplain JacksonJsonObjectMapperProvider} factory
|
||||
* By default this transformer uses {@linkplain org.springframework.integration.support.json.JsonObjectMapperProvider} factory
|
||||
* to get an instance of a Jackson or Jackson 2 JSON-processor {@linkplain JsonObjectMapper} implementation
|
||||
* depending on the jackson-databind or jackson-mapper-asl libs on the classpath.
|
||||
* Any other {@linkplain JsonObjectMapper} implementation can be provided.
|
||||
@@ -56,7 +56,7 @@ public class ObjectToJsonTransformer extends AbstractTransformer {
|
||||
private volatile boolean contentTypeExplicitlySet = false;
|
||||
|
||||
public ObjectToJsonTransformer() {
|
||||
this(JacksonJsonObjectMapperProvider.newInstance());
|
||||
this(JsonObjectMapperProvider.newInstance());
|
||||
}
|
||||
|
||||
public ObjectToJsonTransformer(JsonObjectMapper<?, ?> jsonObjectMapper) {
|
||||
@@ -64,7 +64,7 @@ public class ObjectToJsonTransformer extends AbstractTransformer {
|
||||
}
|
||||
|
||||
public ObjectToJsonTransformer(ResultType resultType) {
|
||||
this(JacksonJsonObjectMapperProvider.newInstance(), resultType);
|
||||
this(JsonObjectMapperProvider.newInstance(), resultType);
|
||||
}
|
||||
|
||||
public ObjectToJsonTransformer(JsonObjectMapper<?, ?> jsonObjectMapper, ResultType resultType) {
|
||||
@@ -113,7 +113,7 @@ public class ObjectToJsonTransformer extends AbstractTransformer {
|
||||
headers.put(MessageHeaders.CONTENT_TYPE, this.contentType);
|
||||
}
|
||||
|
||||
this.jsonObjectMapper.populateJavaTypes(headers, message.getPayload().getClass());
|
||||
this.jsonObjectMapper.populateJavaTypes(headers, message.getPayload());
|
||||
|
||||
messageBuilder.copyHeaders(headers);
|
||||
return messageBuilder.build();
|
||||
|
||||
@@ -104,7 +104,7 @@ public class RecipientListRouter extends AbstractMessageRouter
|
||||
|
||||
/**
|
||||
* Set the recipients for this router.
|
||||
* @param recipientMappings, map contains channelName and expression
|
||||
* @param recipientMappings map contains channelName and expression
|
||||
*/
|
||||
@Override
|
||||
@ManagedAttribute
|
||||
|
||||
@@ -38,7 +38,8 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class AbstractJacksonJsonObjectMapper<N, P, J> implements JsonObjectMapper<N, P>, BeanClassLoaderAware {
|
||||
public abstract class AbstractJacksonJsonObjectMapper<N, P, J> extends JsonObjectMapperAdapter<N, P>
|
||||
implements BeanClassLoaderAware {
|
||||
|
||||
protected static final Collection<Class<?>> supportedJsonTypes =
|
||||
Arrays.<Class<?>> asList(String.class, byte[].class, File.class, URL.class, InputStream.class, Reader.class);
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
package org.springframework.integration.support.json;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.PipedReader;
|
||||
import java.io.PipedWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.boon.json.JsonFactory;
|
||||
import org.boon.json.JsonParserAndMapper;
|
||||
import org.boon.json.JsonParserFactory;
|
||||
import org.boon.json.JsonSerializerFactory;
|
||||
import org.boon.json.JsonSlurper;
|
||||
import org.boon.json.ObjectMapper;
|
||||
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.integration.mapping.support.JsonHeaders;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* The Boon (@link https://github.com/RichardHightower/boon) {@link JsonObjectMapper} implementation.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 4.1
|
||||
*/
|
||||
public class BoonJsonObjectMapper extends JsonObjectMapperAdapter<Map<String, Object>, Object>
|
||||
implements BeanClassLoaderAware {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(BoonJsonObjectMapper.class);
|
||||
|
||||
private static final Collection<Class<?>> supportedJsonTypes =
|
||||
Arrays.<Class<?>>asList(String.class, byte[].class, byte[].class, File.class, InputStream.class, Reader.class);
|
||||
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final JsonSlurper slurper = new JsonSlurper();
|
||||
|
||||
private volatile ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
public BoonJsonObjectMapper() {
|
||||
this.objectMapper = JsonFactory.create();
|
||||
}
|
||||
|
||||
public BoonJsonObjectMapper(JsonParserFactory parserFactory, JsonSerializerFactory serializerFactory) {
|
||||
this.objectMapper = JsonFactory.create(parserFactory, serializerFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toJson(Object value) throws Exception {
|
||||
return this.objectMapper.writeValueAsString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toJson(Object value, Writer writer) {
|
||||
this.objectMapper.toJson(value, writer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> toJsonNode(final Object value) throws Exception {
|
||||
PipedReader in = new PipedReader();
|
||||
final PipedWriter out = new PipedWriter(in);
|
||||
Executors.newSingleThreadExecutor()
|
||||
.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
toJson(value, out);
|
||||
}
|
||||
});
|
||||
return (Map<String, Object>) this.slurper.parse(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T fromJson(Object json, Class<T> type) throws Exception {
|
||||
if (json instanceof String) {
|
||||
return this.objectMapper.readValue((String) json, type);
|
||||
}
|
||||
else if (json instanceof byte[]) {
|
||||
return this.objectMapper.readValue((byte[]) json, type);
|
||||
}
|
||||
else if (json instanceof char[]) {
|
||||
return this.objectMapper.readValue((char[]) json, type);
|
||||
}
|
||||
else if (json instanceof File) {
|
||||
return this.objectMapper.readValue((File) json, type);
|
||||
}
|
||||
else if (json instanceof InputStream) {
|
||||
return this.objectMapper.readValue((InputStream) json, type);
|
||||
}
|
||||
else if (json instanceof Reader) {
|
||||
return this.objectMapper.readValue((Reader) json, type);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("'json' argument must be an instance of: " + supportedJsonTypes
|
||||
+ " , but gotten: " + json.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromJson(Object json, Map<String, Object> javaTypes) throws Exception {
|
||||
JsonParserAndMapper parser = this.objectMapper.parser();
|
||||
|
||||
Class<?> classType = this.createJavaType(javaTypes, JsonHeaders.TYPE_ID);
|
||||
|
||||
Class<?> contentClassType = this.createJavaType(javaTypes, JsonHeaders.CONTENT_TYPE_ID);
|
||||
|
||||
Class<?> keyClassType = this.createJavaType(javaTypes, JsonHeaders.KEY_TYPE_ID);
|
||||
|
||||
if (keyClassType != null) {
|
||||
logger.warn("Boon doesn't support the Map 'key' conversion. Will be returned raw Map<String, Object>");
|
||||
if (json instanceof String) {
|
||||
return (T) parser.parseMap((String) json);
|
||||
}
|
||||
else if (json instanceof byte[]) {
|
||||
return (T) parser.parseMap((byte[]) json);
|
||||
}
|
||||
else if (json instanceof char[]) {
|
||||
return (T) parser.parseMap((char[]) json);
|
||||
}
|
||||
else if (json instanceof File) {
|
||||
return (T) parser.parseMap(new FileReader((File) json));
|
||||
}
|
||||
else if (json instanceof InputStream) {
|
||||
return (T) parser.parseMap((InputStream) json);
|
||||
}
|
||||
else if (json instanceof Reader) {
|
||||
return (T) parser.parseMap((Reader) json);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("'json' argument must be an instance of: " + supportedJsonTypes
|
||||
+ " , but gotten: " + json.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
if (contentClassType != null) {
|
||||
if (json instanceof String) {
|
||||
return (T) this.objectMapper.readValue((String) json, (Class<Collection>) classType, contentClassType);
|
||||
}
|
||||
else if (json instanceof byte[]) {
|
||||
return (T) this.objectMapper.readValue((byte[]) json, (Class<Collection>) classType, contentClassType);
|
||||
}
|
||||
else if (json instanceof char[]) {
|
||||
return (T) this.objectMapper.readValue((char[]) json, (Class<Collection>) classType, contentClassType);
|
||||
}
|
||||
else if (json instanceof File) {
|
||||
return (T) this.objectMapper.readValue((File) json, (Class<Collection>) classType, contentClassType);
|
||||
}
|
||||
else if (json instanceof InputStream) {
|
||||
return (T) this.objectMapper.readValue((InputStream) json, (Class<Collection>) classType,
|
||||
contentClassType);
|
||||
}
|
||||
else if (json instanceof Reader) {
|
||||
return (T) this.objectMapper.readValue((Reader) json, (Class<Collection>) classType, contentClassType);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("'json' argument must be an instance of: " + supportedJsonTypes
|
||||
+ " , but gotten: " + json.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
return (T) fromJson(json, classType);
|
||||
}
|
||||
|
||||
protected Class<?> createJavaType(Map<String, Object> javaTypes, String javaTypeKey) throws Exception {
|
||||
Object classValue = javaTypes.get(javaTypeKey);
|
||||
if (classValue instanceof Class<?>) {
|
||||
return (Class<?>) classValue;
|
||||
}
|
||||
else if (classValue != null) {
|
||||
return ClassUtils.forName(classValue.toString(), this.classLoader);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T fromJson(Object parser, Type valueType) throws Exception {
|
||||
throw new UnsupportedOperationException("Boon doesn't support JSON reader parser abstraction");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,14 +25,14 @@ import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.integration.mapping.support.JsonHeaders;
|
||||
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;
|
||||
|
||||
import org.springframework.integration.mapping.support.JsonHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jackson 2 JSON-processor (@link https://github.com/FasterXML) {@linkplain JsonObjectMapper} implementation.
|
||||
* Delegates <code>toJson</code> and <code>fromJson</code>
|
||||
@@ -90,7 +90,8 @@ public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper<Js
|
||||
return this.objectMapper.readValue((Reader) json, type);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("'json' argument must be an instance of: " + supportedJsonTypes);
|
||||
throw new IllegalArgumentException("'json' argument must be an instance of: " + supportedJsonTypes
|
||||
+ " , but gotten: " + json.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,20 +100,6 @@ public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper<Js
|
||||
return this.objectMapper.readValue(parser, this.constructType(valueType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateJavaTypes(Map<String, Object> map, Class<?> sourceClass) {
|
||||
JavaType javaType = this.objectMapper.constructType(sourceClass);
|
||||
map.put(JsonHeaders.TYPE_ID, javaType.getRawClass());
|
||||
|
||||
if (javaType.isContainerType() && !javaType.isArrayType()) {
|
||||
map.put(JsonHeaders.CONTENT_TYPE_ID, javaType.getContentType().getRawClass());
|
||||
}
|
||||
|
||||
if (javaType.getKeyType() != null) {
|
||||
map.put(JsonHeaders.KEY_TYPE_ID, javaType.getKeyType().getRawClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected JavaType extractJavaType(Map<String, Object> javaTypes) throws Exception {
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
* 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.springframework.integration.support.json;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.codehaus.jackson.JsonFactory;
|
||||
import org.codehaus.jackson.JsonParser;
|
||||
import org.codehaus.jackson.JsonToken;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link JsonInboundMessageMapper.JsonMessageParser} implementation that parses JSON messages
|
||||
* and builds a {@link Message} with the specified payload type from provided {@link JsonInboundMessageMapper}.
|
||||
* Uses Jackson JSON-processor (@link http://jackson.codehaus.org).
|
||||
*
|
||||
* @deprecated Please migrate to {@link Jackson2JsonMessageParser} for Jackson 2.x.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
@Deprecated
|
||||
public class JacksonJsonMessageParser extends AbstractJacksonJsonMessageParser<JsonParser> {
|
||||
|
||||
public JacksonJsonMessageParser() {
|
||||
super(new JacksonJsonObjectMapper());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsonParser createJsonParser(String jsonMessage) throws Exception {
|
||||
return new JsonFactory().createJsonParser(jsonMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Message<?> parseWithHeaders(JsonParser parser, String jsonMessage) throws Exception {
|
||||
String error = AbstractJsonInboundMessageMapper.MESSAGE_FORMAT_ERROR + jsonMessage;
|
||||
Assert.isTrue(parser.nextToken() == JsonToken.START_OBJECT, error);
|
||||
Map<String, Object> headers = null;
|
||||
Object payload = null;
|
||||
while (parser.nextToken() != JsonToken.END_OBJECT) {
|
||||
Assert.isTrue(parser.getCurrentToken() == JsonToken.FIELD_NAME, error);
|
||||
boolean isHeadersToken = "headers".equals(parser.getCurrentName());
|
||||
boolean isPayloadToken = "payload".equals(parser.getCurrentName());
|
||||
Assert.isTrue(isHeadersToken || isPayloadToken, error);
|
||||
if (isHeadersToken) {
|
||||
Assert.isTrue(parser.nextToken() == JsonToken.START_OBJECT, error);
|
||||
headers = readHeaders(parser, jsonMessage);
|
||||
}
|
||||
else if (isPayloadToken) {
|
||||
parser.nextToken();
|
||||
payload = this.readPayload(parser, jsonMessage);
|
||||
}
|
||||
}
|
||||
Assert.notNull(headers, error);
|
||||
return this.getMessageBuilderFactory().withPayload(payload).copyHeaders(headers).build();
|
||||
}
|
||||
|
||||
private Map<String, Object> readHeaders(JsonParser parser, String jsonMessage) throws Exception {
|
||||
Map<String, Object> headers = new LinkedHashMap<String, Object>();
|
||||
while (parser.nextToken() != JsonToken.END_OBJECT) {
|
||||
String headerName = parser.getCurrentName();
|
||||
parser.nextToken();
|
||||
Object headerValue = this.readHeader(parser, headerName, jsonMessage);
|
||||
headers.put(headerName, headerValue);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.springframework.integration.support.json;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
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;
|
||||
|
||||
import org.springframework.integration.mapping.support.JsonHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Jackson JSON-processor (@link http://jackson.codehaus.org) {@linkplain JsonObjectMapper} implementation.
|
||||
* Delegates <code>toJson</code> and <code>fromJson</code>
|
||||
* to the {@linkplain org.codehaus.jackson.map.ObjectMapper}
|
||||
*
|
||||
* @deprecated Please migrate to {@link Jackson2JsonObjectMapper} for Jackson 2.x.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
@Deprecated
|
||||
public class JacksonJsonObjectMapper extends AbstractJacksonJsonObjectMapper<JsonNode, JsonParser, JavaType> {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public JacksonJsonObjectMapper() {
|
||||
this.objectMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
public JacksonJsonObjectMapper(ObjectMapper objectMapper) {
|
||||
Assert.notNull(objectMapper, "objectMapper must not be null");
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toJson(Object value) throws Exception {
|
||||
return this.objectMapper.writeValueAsString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toJson(Object value, Writer writer) throws Exception {
|
||||
this.objectMapper.writeValue(writer, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonNode toJsonNode(Object value) throws Exception {
|
||||
return this.objectMapper.valueToTree(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T fromJson(JsonParser parser, Type valueType) throws Exception {
|
||||
return this.objectMapper.readValue(parser, this.constructType(valueType));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> T fromJson(Object json, JavaType type) throws Exception {
|
||||
if (json instanceof String) {
|
||||
return this.objectMapper.readValue((String) json, type);
|
||||
}
|
||||
else if(json instanceof byte[]) {
|
||||
return this.objectMapper.readValue((byte[]) json, type);
|
||||
}
|
||||
else if (json instanceof File) {
|
||||
return this.objectMapper.readValue((File) json, type);
|
||||
}
|
||||
else if (json instanceof URL) {
|
||||
return this.objectMapper.readValue((URL) json, type);
|
||||
}
|
||||
else if (json instanceof InputStream) {
|
||||
return this.objectMapper.readValue((InputStream) json, type);
|
||||
}
|
||||
else if (json instanceof Reader) {
|
||||
return this.objectMapper.readValue((Reader) json, type);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("'json' argument must be an instance of: " + supportedJsonTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateJavaTypes(Map<String, Object> map, Class<?> sourceClass) {
|
||||
JavaType javaType = this.constructType(sourceClass);
|
||||
map.put(JsonHeaders.TYPE_ID, javaType.getRawClass());
|
||||
|
||||
if (javaType.isContainerType() && !javaType.isArrayType()) {
|
||||
map.put(JsonHeaders.CONTENT_TYPE_ID, javaType.getContentType().getRawClass());
|
||||
}
|
||||
|
||||
if (javaType.getKeyType() != null) {
|
||||
map.put(JsonHeaders.KEY_TYPE_ID, javaType.getKeyType().getRawClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JavaType constructType(Type type) {
|
||||
return this.objectMapper.constructType(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected JavaType extractJavaType(Map<String, Object> javaTypes) throws Exception {
|
||||
JavaType classType = this.createJavaType(javaTypes, JsonHeaders.TYPE_ID);
|
||||
if (!classType.isContainerType() || classType.isArrayType()) {
|
||||
return classType;
|
||||
}
|
||||
|
||||
JavaType contentClassType = this.createJavaType(javaTypes, JsonHeaders.CONTENT_TYPE_ID);
|
||||
if (classType.getKeyType() == null) {
|
||||
return this.objectMapper.getTypeFactory()
|
||||
.constructCollectionType((Class<? extends Collection<?>>) classType.getRawClass(), contentClassType);
|
||||
}
|
||||
|
||||
JavaType keyClassType = this.createJavaType(javaTypes, JsonHeaders.KEY_TYPE_ID);
|
||||
return this.objectMapper.getTypeFactory()
|
||||
.constructMapType((Class<? extends Map<?, ?>>) classType.getRawClass(), keyClassType, contentClassType);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,9 +38,6 @@ public final class JacksonJsonUtils {
|
||||
ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", classLoader) &&
|
||||
ClassUtils.isPresent("org.codehaus.jackson.JsonGenerator", classLoader);
|
||||
|
||||
private static final IllegalStateException NO_JACKSON_LIB_EXCEPTION =
|
||||
new IllegalStateException("Neither jackson-databind.jar, nor jackson-mapper-asl.jar aren't presented in the classpath.");
|
||||
|
||||
public static boolean isJackson2Present() {
|
||||
return jackson2Present;
|
||||
}
|
||||
@@ -49,7 +46,4 @@ public final class JacksonJsonUtils {
|
||||
return jacksonPresent;
|
||||
}
|
||||
|
||||
public static IllegalStateException getNoJacksonLibException() {
|
||||
return NO_JACKSON_LIB_EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,5 +44,5 @@ public interface JsonObjectMapper<N, P> {
|
||||
|
||||
<T> T fromJson(P parser, Type valueType) throws Exception;
|
||||
|
||||
void populateJavaTypes(Map<String, Object> map, Class<?> sourceClass);
|
||||
void populateJavaTypes(Map<String, Object> map, Object object);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,11 @@ package org.springframework.integration.support.json;
|
||||
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.integration.mapping.support.JsonHeaders;
|
||||
|
||||
/**
|
||||
* Simple {@linkplain JsonObjectMapper} adapter implementation, if there is no need
|
||||
* to provide entire operations implementation.
|
||||
@@ -59,7 +62,15 @@ public abstract class JsonObjectMapperAdapter<N, P> implements JsonObjectMapper<
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populateJavaTypes(Map<String, Object> map, Class<?> sourceClass) {
|
||||
public void populateJavaTypes(Map<String, Object> map, Object object) {
|
||||
map.put(JsonHeaders.TYPE_ID, object.getClass());
|
||||
if (object instanceof Collection && !((Collection) object).isEmpty()) {
|
||||
map.put(JsonHeaders.CONTENT_TYPE_ID, ((Collection) object).iterator().next().getClass());
|
||||
}
|
||||
if (object instanceof Map && !((Map) object).isEmpty()) {
|
||||
map.put(JsonHeaders.CONTENT_TYPE_ID, ((Map) object).values().iterator().next().getClass());
|
||||
map.put(JsonHeaders.KEY_TYPE_ID, ((Map) object).keySet().iterator().next().getClass());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
package org.springframework.integration.support.json;
|
||||
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Simple factory to provide {@linkplain Jackson2JsonObjectMapper} or {@linkplain JacksonJsonObjectMapper}
|
||||
* instances dependently of jackson-databind or jackson-mapper-asl libs in the classpath.
|
||||
* Simple factory to provide {@linkplain JsonObjectMapper}
|
||||
* instances dependently of jackson-databind or boon libs in the classpath.
|
||||
* If there are both libs in the classpath, it prefers Jackson 2 JSON-processor implementation.
|
||||
* If there is not any of them, {@linkplain IllegalStateException} will be thrown.
|
||||
*
|
||||
@@ -28,18 +30,25 @@ package org.springframework.integration.support.json;
|
||||
* @since 3.0
|
||||
*
|
||||
* @see Jackson2JsonObjectMapper
|
||||
* @see org.springframework.integration.support.json.BoonJsonObjectMapper
|
||||
*/
|
||||
public final class JacksonJsonObjectMapperProvider {
|
||||
public final class JsonObjectMapperProvider {
|
||||
|
||||
private static final ClassLoader classLoader = JsonObjectMapperProvider.class.getClassLoader();
|
||||
|
||||
private static final boolean boonPresent =
|
||||
ClassUtils.isPresent("org.boon.json.ObjectMapper", classLoader);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static JsonObjectMapper<?, ?> newInstance() {
|
||||
if (JacksonJsonUtils.isJackson2Present()) {
|
||||
return new Jackson2JsonObjectMapper();
|
||||
}
|
||||
if(JacksonJsonUtils.isJacksonPresent()) {
|
||||
return new JacksonJsonObjectMapper();
|
||||
else if (boonPresent) {
|
||||
return new BoonJsonObjectMapper();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Neither jackson-databind.jar, nor boon.jar is present in the classpath.");
|
||||
}
|
||||
throw JacksonJsonUtils.getNoJacksonLibException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public class JsonOutboundMessageMapper implements OutboundMessageMapper<String>
|
||||
private volatile JsonObjectMapper<?, ?> jsonObjectMapper;
|
||||
|
||||
public JsonOutboundMessageMapper() {
|
||||
this(JacksonJsonObjectMapperProvider.newInstance());
|
||||
this(JsonObjectMapperProvider.newInstance());
|
||||
}
|
||||
|
||||
public JsonOutboundMessageMapper(JsonObjectMapper<?, ?> jsonObjectMapper) {
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.integration.support.json.JacksonJsonObjectMapperProvider;
|
||||
import org.springframework.integration.support.json.JsonObjectMapperProvider;
|
||||
import org.springframework.integration.support.json.JsonObjectMapper;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -54,7 +54,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class ObjectToMapTransformer extends AbstractPayloadTransformer<Object, Map<?,?>> {
|
||||
|
||||
private final JsonObjectMapper<?, ?> jsonObjectMapper = JacksonJsonObjectMapperProvider.newInstance();
|
||||
private final JsonObjectMapper<?, ?> jsonObjectMapper = JsonObjectMapperProvider.newInstance();
|
||||
|
||||
private volatile boolean shouldFlattenKeys = true;
|
||||
|
||||
|
||||
@@ -33,10 +33,10 @@ import org.junit.Test;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.integration.message.MessageMatcher;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.support.json.JacksonJsonObjectMapperProvider;
|
||||
import org.springframework.integration.support.json.JsonInboundMessageMapper;
|
||||
import org.springframework.integration.support.json.JsonInboundMessageMapper.JsonMessageParser;
|
||||
import org.springframework.integration.support.json.JsonObjectMapper;
|
||||
import org.springframework.integration.support.json.JsonObjectMapperProvider;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ import org.springframework.messaging.Message;
|
||||
*/
|
||||
public abstract class AbstractJsonInboundMessageMapperTests {
|
||||
|
||||
private final JsonObjectMapper<?, ?> mapper = JacksonJsonObjectMapperProvider.newInstance();
|
||||
private final JsonObjectMapper<?, ?> mapper = JsonObjectMapperProvider.newInstance();
|
||||
|
||||
@Factory
|
||||
public static Matcher<Message<?>> sameExceptImmutableHeaders(Message<?> operand) {
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
* 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.springframework.integration.json;
|
||||
|
||||
import org.springframework.integration.support.json.JsonInboundMessageMapper.JsonMessageParser;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 3.0
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class JacksonJsonInboundMessageMapperTests extends AbstractJsonInboundMessageMapperTests {
|
||||
|
||||
@Override
|
||||
protected JsonMessageParser<?> getParser() {
|
||||
return new org.springframework.integration.support.json.JacksonJsonMessageParser();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
* 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.springframework.integration.json;
|
||||
|
||||
import org.springframework.integration.support.json.JsonInboundMessageMapper.JsonMessageParser;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 3.0
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class JacksonJsonSymmetricalMessageMappingTests extends AbstractJsonSymmetricalMessageMappingTests {
|
||||
|
||||
@Override
|
||||
protected JsonMessageParser<?> getParser() {
|
||||
return new org.springframework.integration.support.json.JacksonJsonMessageParser();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,16 +16,14 @@
|
||||
|
||||
package org.springframework.integration.json;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.codehaus.jackson.JsonFactory;
|
||||
import org.codehaus.jackson.JsonParseException;
|
||||
import org.codehaus.jackson.JsonParser;
|
||||
import org.codehaus.jackson.JsonToken;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.history.MessageHistory;
|
||||
@@ -112,8 +110,8 @@ public class JsonOutboundMessageMapperTests {
|
||||
assertEquals(payload, parsedPayload);
|
||||
}
|
||||
|
||||
private TestBean extractJsonPayloadToTestBean(String json) throws JsonParseException, IOException {
|
||||
JsonParser parser = jsonFactory.createJsonParser(json);
|
||||
private TestBean extractJsonPayloadToTestBean(String json) throws IOException {
|
||||
JsonParser parser = jsonFactory.createParser(json);
|
||||
do {
|
||||
parser.nextToken();
|
||||
} while(parser.getCurrentToken() != JsonToken.FIELD_NAME || !parser.getCurrentName().equals("payload"));
|
||||
|
||||
@@ -16,16 +16,16 @@
|
||||
|
||||
package org.springframework.integration.json;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.support.json.Jackson2JsonObjectMapper;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.support.json.BoonJsonObjectMapper;
|
||||
import org.springframework.integration.support.json.Jackson2JsonObjectMapper;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
@@ -62,4 +62,17 @@ public class JsonToObjectTransformerTests {
|
||||
assertEquals("123 Main Street", person.getAddress().toString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBoonJsonObjectMapper() throws Exception {
|
||||
JsonToObjectTransformer transformer = new JsonToObjectTransformer(TestPerson.class, new BoonJsonObjectMapper());
|
||||
String jsonString = "{\"firstName\":\"John\",\"lastName\":\"Doe\",\"age\":42,\"address\":{\"number\":123,\"street\":\"Main Street\"}}";
|
||||
Message<?> message = transformer.transform(new GenericMessage<String>(jsonString));
|
||||
TestPerson person = (TestPerson) message.getPayload();
|
||||
assertEquals("John", person.getFirstName());
|
||||
assertEquals("Doe", person.getLastName());
|
||||
assertEquals(42, person.getAge());
|
||||
assertEquals("123 Main Street", person.getAddress().toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,10 +16,15 @@
|
||||
|
||||
package org.springframework.integration.json;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.support.json.BoonJsonObjectMapper;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
@@ -35,13 +40,35 @@ public class JsonTransformersSymmetricalTests {
|
||||
TestPerson person = new TestPerson("John", "Doe", 42);
|
||||
person.setAddress(new TestAddress(123, "Main Street"));
|
||||
|
||||
List<TestPerson> payload = new ArrayList<TestPerson>();
|
||||
payload.add(person);
|
||||
|
||||
ObjectToJsonTransformer objectToJsonTransformer = new ObjectToJsonTransformer();
|
||||
Message<?> jsonMessage = objectToJsonTransformer.transform(new GenericMessage<Object>(person));
|
||||
Message<?> jsonMessage = objectToJsonTransformer.transform(new GenericMessage<Object>(payload));
|
||||
|
||||
JsonToObjectTransformer jsonToObjectTransformer = new JsonToObjectTransformer();
|
||||
Message<?> result = jsonToObjectTransformer.transform(jsonMessage);
|
||||
|
||||
assertEquals(person, result.getPayload());
|
||||
Object result = jsonToObjectTransformer.transform(jsonMessage).getPayload();
|
||||
assertThat(result, Matchers.instanceOf(List.class));
|
||||
assertEquals(person, ((List) result).get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoonObjectToJson_JsonToObject() {
|
||||
|
||||
TestPerson person = new TestPerson("John", "Doe", 42);
|
||||
person.setAddress(new TestAddress(123, "Main Street"));
|
||||
|
||||
List<TestPerson> payload = new ArrayList<TestPerson>();
|
||||
payload.add(person);
|
||||
|
||||
ObjectToJsonTransformer objectToJsonTransformer = new ObjectToJsonTransformer(new BoonJsonObjectMapper());
|
||||
Message<?> jsonMessage = objectToJsonTransformer.transform(new GenericMessage<Object>(payload));
|
||||
|
||||
JsonToObjectTransformer jsonToObjectTransformer = new JsonToObjectTransformer(new BoonJsonObjectMapper());
|
||||
Object result = jsonToObjectTransformer.transform(jsonMessage).getPayload();
|
||||
assertThat(result, Matchers.instanceOf(List.class));
|
||||
assertEquals(person, ((List) result).get(0));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
|
||||
<object-to-json-transformer id="jsonNodeTransformer" input-channel="jsonNodeInput" result-type="NODE"/>
|
||||
|
||||
<object-to-json-transformer input-channel="boonJsonNodeInput" result-type="NODE"
|
||||
object-mapper="boonJsonObjectMapper"/>
|
||||
|
||||
<beans:bean id="boonJsonObjectMapper" class="org.springframework.integration.support.json.BoonJsonObjectMapper"/>
|
||||
|
||||
<beans:bean id="customJsonObjectMapper" class="org.springframework.integration.json.ObjectToJsonTransformerParserTests$CustomJsonObjectMapper"/>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -16,15 +16,13 @@
|
||||
|
||||
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 static org.junit.Assert.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -35,6 +33,7 @@ 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.mapping.support.JsonHeaders;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.support.json.Jackson2JsonObjectMapper;
|
||||
import org.springframework.integration.support.json.JsonObjectMapperAdapter;
|
||||
@@ -45,8 +44,6 @@ 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
|
||||
@@ -70,6 +67,9 @@ public class ObjectToJsonTransformerParserTests {
|
||||
@Autowired
|
||||
private volatile MessageChannel jsonNodeInput;
|
||||
|
||||
@Autowired
|
||||
private volatile MessageChannel boonJsonNodeInput;
|
||||
|
||||
@Test
|
||||
public void testContentType(){
|
||||
ObjectToJsonTransformer transformer =
|
||||
@@ -165,6 +165,25 @@ public class ObjectToJsonTransformerParserTests {
|
||||
assertTrue(expression.getValue(evaluationContext, payload, Boolean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoonNodeResultType() {
|
||||
TestPerson person = new TestPerson();
|
||||
person.setFirstName("John");
|
||||
person.setLastName("Doe");
|
||||
person.setAge(42);
|
||||
QueueChannel replyChannel = new QueueChannel();
|
||||
Message<TestPerson> message = MessageBuilder.withPayload(person).setReplyChannel(replyChannel).build();
|
||||
this.boonJsonNodeInput.send(message);
|
||||
Message<?> reply = replyChannel.receive(0);
|
||||
assertNotNull(reply);
|
||||
Object payload = reply.getPayload();
|
||||
assertThat(payload, Matchers.instanceOf(Map.class));
|
||||
assertEquals(TestPerson.class, reply.getHeaders().get(JsonHeaders.TYPE_ID));
|
||||
|
||||
Expression expression = new SpelExpressionParser().parseExpression("[firstName] == 'John' and [age] == 42");
|
||||
assertTrue(expression.getValue(new StandardEvaluationContext(), payload, Boolean.class));
|
||||
}
|
||||
|
||||
static class CustomJsonObjectMapper extends JsonObjectMapperAdapter<Object, Object> {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,16 +16,24 @@
|
||||
|
||||
package org.springframework.integration.json;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.support.json.BoonJsonObjectMapper;
|
||||
import org.springframework.integration.support.json.Jackson2JsonObjectMapper;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
@@ -142,4 +150,39 @@ public class ObjectToJsonTransformerTests {
|
||||
assertTrue(addressResult.contains("street:\"Main Street\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoonJsonObjectMapper() throws Exception {
|
||||
ObjectToJsonTransformer transformer = new ObjectToJsonTransformer(new BoonJsonObjectMapper());
|
||||
TestPerson person = new TestPerson("John", "Doe", 42);
|
||||
person.setAddress(new TestAddress(123, "Main Street"));
|
||||
String result = (String) transformer.transform(new GenericMessage<TestPerson>(person)).getPayload();
|
||||
assertTrue(result.contains("\"firstName\":\"John\""));
|
||||
assertTrue(result.contains("\"lastName\":\"Doe\""));
|
||||
assertTrue(result.contains("\"age\":42"));
|
||||
Pattern addressPattern = Pattern.compile("(\"address\":\\{.*?\\})");
|
||||
Matcher matcher = addressPattern.matcher(result);
|
||||
assertTrue(matcher.find());
|
||||
String addressResult = matcher.group(1);
|
||||
assertTrue(addressResult.contains("\"number\":123"));
|
||||
assertTrue(addressResult.contains("\"street\":\"Main Street\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBoonJsonObjectMapper_toNode() throws Exception {
|
||||
ObjectToJsonTransformer transformer = new ObjectToJsonTransformer(new BoonJsonObjectMapper(),
|
||||
ObjectToJsonTransformer.ResultType.NODE);
|
||||
TestPerson person = new TestPerson("John", "Doe", 42);
|
||||
person.setAddress(new TestAddress(123, "Main Street"));
|
||||
Object payload = transformer.transform(new GenericMessage<TestPerson>(person)).getPayload();
|
||||
assertThat(payload, instanceOf(Map.class));
|
||||
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
Expression expression = parser.parseExpression("firstName + ': ' + address.street");
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
||||
evaluationContext.addPropertyAccessor(new MapAccessor());
|
||||
String value = expression.getValue(evaluationContext, payload, String.class);
|
||||
|
||||
assertEquals("John: Main Street", value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.integration.transformer;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
@@ -23,22 +25,15 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.codehaus.jackson.JsonGenerationException;
|
||||
import org.codehaus.jackson.JsonParseException;
|
||||
import org.codehaus.jackson.map.JsonMappingException;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -47,9 +42,10 @@ import static org.junit.Assert.assertNull;
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ObjectToMapTransformerTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testObjectToSpelMapTransformer() throws JsonParseException, JsonMappingException, JsonGenerationException, IOException{
|
||||
public void testObjectToSpelMapTransformer() throws IOException {
|
||||
Employee employee = this.buildEmployee();
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
context.addPropertyAccessor(new MapAccessor());
|
||||
|
||||
@@ -26,13 +26,13 @@ import java.util.Map;
|
||||
|
||||
import org.springframework.core.serializer.Deserializer;
|
||||
import org.springframework.core.serializer.Serializer;
|
||||
import org.springframework.integration.support.json.JacksonJsonObjectMapperProvider;
|
||||
import org.springframework.integration.support.json.JsonObjectMapperProvider;
|
||||
import org.springframework.integration.support.json.JsonObjectMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Serializes a {@link Map} as JSON. Deserializes JSON to
|
||||
* a {@link Map}. The default {@link JacksonJsonObjectMapperProvider#newInstance()} can be
|
||||
* a {@link Map}. The default {@link org.springframework.integration.support.json.JsonObjectMapperProvider#newInstance()} can be
|
||||
* overridden using {@link #setJsonObjectMapper(JsonObjectMapper)}.
|
||||
* <p>
|
||||
* The JSON deserializer can't delimit multiple JSON
|
||||
@@ -48,7 +48,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class MapJsonSerializer implements Serializer<Map<?, ?>>, Deserializer<Map<?, ?>> {
|
||||
|
||||
private volatile JsonObjectMapper<?, ?> jsonObjectMapper = JacksonJsonObjectMapperProvider.newInstance();
|
||||
private volatile JsonObjectMapper<?, ?> jsonObjectMapper = JsonObjectMapperProvider.newInstance();
|
||||
|
||||
private volatile Deserializer<byte[]> packetDeserializer = new ByteArrayLfSerializer();
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ public class UdpUnicastEndToEndTests implements Runnable {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tesUudpOutboundChannelAdapterWithinChain() throws Exception {
|
||||
public void tesUdpOutboundChannelAdapterWithinChain() throws Exception {
|
||||
UdpUnicastEndToEndTests launcher = new UdpUnicastEndToEndTests();
|
||||
Thread t = new Thread(launcher);
|
||||
t.start(); // launch the receiver
|
||||
@@ -189,7 +189,7 @@ public class UdpUnicastEndToEndTests implements Runnable {
|
||||
public static void main(String[] args) throws Exception {
|
||||
hangAroundFor = 120000;
|
||||
new UdpUnicastEndToEndTests().runIt();
|
||||
new UdpUnicastEndToEndTests().tesUudpOutboundChannelAdapterWithinChain();
|
||||
new UdpUnicastEndToEndTests().tesUdpOutboundChannelAdapterWithinChain();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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,7 +31,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.data.redis.serializer.JacksonJsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.integration.mapping.InboundMessageMapper;
|
||||
@@ -69,7 +69,8 @@ public class RedisQueueOutboundChannelAdapterTests extends RedisAvailableTests {
|
||||
|
||||
final String queueName = "si.test.testRedisQueueOutboundChannelAdapter";
|
||||
|
||||
final RedisQueueOutboundChannelAdapter handler = new RedisQueueOutboundChannelAdapter(queueName, this.connectionFactory);
|
||||
final RedisQueueOutboundChannelAdapter handler = new RedisQueueOutboundChannelAdapter(queueName,
|
||||
this.connectionFactory);
|
||||
|
||||
String payload = "testing";
|
||||
handler.handleMessage(MessageBuilder.withPayload(payload).build());
|
||||
@@ -105,7 +106,8 @@ public class RedisQueueOutboundChannelAdapterTests extends RedisAvailableTests {
|
||||
|
||||
final String queueName = "si.test.testRedisQueueOutboundChannelAdapter2";
|
||||
|
||||
final RedisQueueOutboundChannelAdapter handler = new RedisQueueOutboundChannelAdapter(queueName, this.connectionFactory);
|
||||
final RedisQueueOutboundChannelAdapter handler = new RedisQueueOutboundChannelAdapter(queueName,
|
||||
this.connectionFactory);
|
||||
handler.setExtractPayload(false);
|
||||
|
||||
Message<String> message = MessageBuilder.withPayload("testing").build();
|
||||
@@ -131,8 +133,9 @@ public class RedisQueueOutboundChannelAdapterTests extends RedisAvailableTests {
|
||||
|
||||
final String queueName = "si.test.testRedisQueueOutboundChannelAdapter2";
|
||||
|
||||
final RedisQueueOutboundChannelAdapter handler = new RedisQueueOutboundChannelAdapter(queueName, this.connectionFactory);
|
||||
handler.setSerializer(new JacksonJsonRedisSerializer<Object>(Object.class));
|
||||
final RedisQueueOutboundChannelAdapter handler = new RedisQueueOutboundChannelAdapter(queueName,
|
||||
this.connectionFactory);
|
||||
handler.setSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
|
||||
|
||||
RedisTemplate<String, ?> redisTemplate = new StringRedisTemplate();
|
||||
redisTemplate.setConnectionFactory(this.connectionFactory);
|
||||
@@ -168,7 +171,8 @@ public class RedisQueueOutboundChannelAdapterTests extends RedisAvailableTests {
|
||||
|
||||
String result = redisTemplate.boundListOps(queueName).rightPop(5000, TimeUnit.MILLISECONDS);
|
||||
assertNotNull(result);
|
||||
InboundMessageMapper<String> mapper = new JsonInboundMessageMapper(String.class, new Jackson2JsonMessageParser());
|
||||
InboundMessageMapper<String> mapper = new JsonInboundMessageMapper(String.class,
|
||||
new Jackson2JsonMessageParser());
|
||||
Message<?> resultMessage = mapper.toMessage(result);
|
||||
assertEquals(message.getPayload(), resultMessage.getPayload());
|
||||
}
|
||||
|
||||
@@ -240,9 +240,9 @@ public class Child {
|
||||
type="foo.MyDomainObject"/>]]></programlisting>
|
||||
</para>
|
||||
<para>
|
||||
These use a vanilla Jackson ObjectMapper by default. If you wish to customize the ObjectMapper (for example,
|
||||
to configure the 'ALLOW_COMMENTS' feature when parsing JSON), you can supply a reference to your custom ObjectMapper bean using
|
||||
the object-mapper attribute.
|
||||
These use a vanilla <interfacename>JsonObjectMapper</interfacename> by default based on implementation from
|
||||
classpath. You can provide your own custom <interfacename>JsonObjectMapper</interfacename> implementation
|
||||
with appropriate options or based on required library (e.g. GSON).
|
||||
</para>
|
||||
<para>
|
||||
<programlisting language="xml"><![CDATA[<int:json-to-object-transformer input-channel="objectMapperInput"
|
||||
@@ -253,29 +253,33 @@ public class Child {
|
||||
Beginning with version 3.0, the <code>object-mapper</code> attribute references an instance of a new
|
||||
strategy interface <interfacename>JsonObjectMapper</interfacename>. This abstraction allows multiple
|
||||
implementations of json mappers to be used. Implementations that wrap
|
||||
<ulink url="http://jackson.codehaus.org">Jackson 1.x</ulink> and
|
||||
<ulink url="https://github.com/RichardHightower/boon">Boon</ulink> and
|
||||
<ulink url="https://github.com/FasterXML">Jackson 2</ulink> are
|
||||
provided, with the version being detected on the classpath. These classes are
|
||||
<classname>JacksonJsonObjectMapper</classname> and <classname>Jackson2JsonObjectMapper</classname>.
|
||||
<classname>BoonJsonObjectMapper</classname> and <classname>Jackson2JsonObjectMapper</classname>.
|
||||
</para>
|
||||
<para>
|
||||
For backward compatibility, a simple Jackson 1.x <classname>ObjectMapper</classname> can be provided
|
||||
instead of a <interfacename>JsonObjectMapper</interfacename>. This will be removed in a future release.
|
||||
Note, <classname>BoonJsonObjectMapper</classname> is provided since <emphasis>version 4.1</emphasis>.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
<important>
|
||||
If there are requirements to use both Jackson libraries in the same application, keep in mind that
|
||||
before version 3.0, the JSON transformers used only Jackson 1.x and, from 3.0 on, the framework will
|
||||
select Jackson 2 by default, if both are on the classpath.
|
||||
So, to avoid unexpected issues with Jackson's mapping features, when using annotations, there may be
|
||||
a need to apply annotations from both Jacksons on domain classes:
|
||||
If there are requirements to use both Jackson libraries and/or Boon in the same application,
|
||||
keep in mind that before version 3.0, the JSON transformers used only Jackson 1.x.
|
||||
From <emphasis>4.1</emphasis> on, the framework will select Jackson 2 by default ahead of the
|
||||
Boon implementation if both are on the classpath.
|
||||
Jackson 1.x is no longer supported by the framework internally but, of course, you can still use it
|
||||
within your code.
|
||||
To avoid unexpected issues with JSON mapping features, when using annotations, there may be
|
||||
a need to apply annotations from both Jacksons and/or Boon on domain classes:
|
||||
<programlisting language="java"><![CDATA[@org.codehaus.jackson.annotate.JsonIgnoreProperties(ignoreUnknown=true)
|
||||
@com.fasterxml.jackson.annotation.JsonIgnoreProperties(ignoreUnknown=true)
|
||||
@org.boon.json.annotations.JsonIgnoreProperties("foo")
|
||||
public class Foo {
|
||||
|
||||
@org.codehaus.jackson.annotate.JsonProperty("fooBar")
|
||||
@com.fasterxml.jackson.annotation.JsonProperty("fooBar")
|
||||
@org.boon.json.annotations.JsonProperty("fooBar")
|
||||
public Object bar;
|
||||
|
||||
}]]></programlisting>
|
||||
@@ -377,6 +381,7 @@ public class Foo {
|
||||
The node JSON representation provides efficiency for using the <classname>JsonPropertyAccessor</classname>, when the
|
||||
downstream message flow uses SpEL expressions with access to the properties of the JSON data. See
|
||||
<xref linkend="spel-property-accessors"/>.
|
||||
When using Boon, the <code>NODE</code> representation is a <interfacename>Map<String, Object></interfacename>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -162,5 +162,13 @@
|
||||
See <xref linkend="amqp-channels"/> for more information.
|
||||
</para>
|
||||
</section>
|
||||
<section id="4.1-json-transformers">
|
||||
<title>BoonJsonObjectMapper</title>
|
||||
<para>
|
||||
The <emphasis>Boon</emphasis> <interfacename>JsonObjectMapper</interfacename> is now provided
|
||||
for the JSON transformers. See <xref linkend="transformer"/> for more information.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
Reference in New Issue
Block a user