INT-3130: Add result-type to <o-to-j-transformer>
JIRA: https://jira.springsource.org/browse/INT-3130 * add `result-type` attribute to the `<object-to-json-transformer>` based on enumeration values: `STRING`, `NODE` * Provide implementations for methods to convert value to the node representation * Refactoring according new generic option in the `JsonObjectMapper` * Add tests and documentation Need Migration Guide note according this refactoring INT-3130: remove some deprecation and JavaDocs Addressed PR comments Doc Polishing
This commit is contained in:
committed by
Gary Russell
parent
9005938ab5
commit
062e7bc9d2
@@ -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"));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<String> messageBuilder = MessageBuilder.withPayload(payload);
|
||||
Object payload = ResultType.STRING.equals(this.resultType)
|
||||
? this.jsonObjectMapper.toJson(message.getPayload())
|
||||
: this.jsonObjectMapper.toJsonNode(message.getPayload());
|
||||
MessageBuilder<Object> messageBuilder = MessageBuilder.withPayload(payload);
|
||||
|
||||
LinkedCaseInsensitiveMap<Object> headers = new LinkedCaseInsensitiveMap<Object>();
|
||||
headers.putAll(message.getHeaders());
|
||||
|
||||
@@ -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<P> implements JsonInboundMessageMapper.JsonMessageParser<P> {
|
||||
|
||||
private final JsonObjectMapper<P> objectMapper;
|
||||
private final JsonObjectMapper<?, P> objectMapper;
|
||||
|
||||
private volatile JsonInboundMessageMapper messageMapper;
|
||||
|
||||
protected AbstractJacksonJsonMessageParser(JsonObjectMapper<P> objectMapper) {
|
||||
protected AbstractJacksonJsonMessageParser(JsonObjectMapper<?, P> objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <N> - The expected type of JSON Node.
|
||||
* @param <P> - The expected type of JSON Parser.
|
||||
* @param <J> - The expected type of Java Type representation.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class AbstractJacksonJsonObjectMapper<P, J> implements JsonObjectMapper<P>, BeanClassLoaderAware {
|
||||
public abstract class AbstractJacksonJsonObjectMapper<N, P, J> implements JsonObjectMapper<N, P>, BeanClassLoaderAware {
|
||||
|
||||
protected static final Collection<Class<?>> supportedJsonTypes =
|
||||
Arrays.<Class<?>> asList(String.class, byte[].class, File.class, URL.class, InputStream.class, Reader.class);
|
||||
|
||||
@@ -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<JsonParser, JavaType> {
|
||||
public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper<JsonNode, JsonParser, JavaType> {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@@ -63,6 +64,11 @@ public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper<Js
|
||||
this.objectMapper.writeValue(writer, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonNode toJsonNode(Object value) throws Exception {
|
||||
return this.objectMapper.valueToTree(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> T fromJson(Object json, JavaType type) throws Exception {
|
||||
if (json instanceof String) {
|
||||
|
||||
@@ -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<JsonParser, JavaType> {
|
||||
public class JacksonJsonObjectMapper extends AbstractJacksonJsonObjectMapper<JsonNode, JsonParser, JavaType> {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@@ -66,6 +67,11 @@ public class JacksonJsonObjectMapper extends AbstractJacksonJsonObjectMapper<Jso
|
||||
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));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 <N> - The expected type of JSON Node.
|
||||
* @param <P> - The expected type of JSON Parser.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*
|
||||
*/
|
||||
public interface JsonObjectMapper<P> {
|
||||
public interface JsonObjectMapper<N, P> {
|
||||
|
||||
String toJson(Object value) throws Exception;
|
||||
|
||||
void toJson(Object value, Writer writer) throws Exception;
|
||||
|
||||
N toJsonNode(Object value) throws Exception;
|
||||
|
||||
<T> T fromJson(Object json, Class<T> valueType) throws Exception;
|
||||
|
||||
<T> T fromJson(Object json, Map<String, Object> javaTypes) throws Exception;
|
||||
|
||||
@@ -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<P> implements JsonObjectMapper<P> {
|
||||
public abstract class JsonObjectMapperAdapter<N, P> implements JsonObjectMapper<N, P> {
|
||||
|
||||
@Override
|
||||
public String toJson(Object value) throws Exception {
|
||||
@@ -38,6 +38,11 @@ public abstract class JsonObjectMapperAdapter<P> implements JsonObjectMapper<P>
|
||||
public void toJson(Object value, Writer writer) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public N toJsonNode(Object value) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T fromJson(Object json, Class<T> valueType) throws Exception {
|
||||
return null;
|
||||
|
||||
@@ -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<String>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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<Object, Map<?,?>> {
|
||||
|
||||
private final JsonObjectMapper<?> jsonObjectMapper = JacksonJsonObjectMapperProvider.newInstance();
|
||||
private final JsonObjectMapper<?, ?> jsonObjectMapper = JacksonJsonObjectMapperProvider.newInstance();
|
||||
|
||||
private volatile boolean shouldFlattenKeys = true;
|
||||
|
||||
|
||||
@@ -2263,17 +2263,37 @@
|
||||
This Jackson 1 ObjectMapper backward compatibility is deprecated
|
||||
and will be removed in the Spring Integration 3.1 or above.
|
||||
</xsd:documentation>
|
||||
<!-- TODO: Revert in the Spring Integration 3.1 or above after removing Jackson 1 backward compatibility
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.support.json.JsonObjectMapper" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>-->
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="result-type" default="STRING">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="jsonResultTypeEnumeration xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:simpleType name="jsonResultTypeEnumeration">
|
||||
<xsd:restriction base="xsd:token">
|
||||
<xsd:enumeration value="STRING" />
|
||||
<xsd:enumeration value="NODE" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
|
||||
<xsd:element name="json-to-object-transformer">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -2310,12 +2330,11 @@
|
||||
This Jackson 1 ObjectMapper backward compatibility is deprecated
|
||||
and will be removed in the Spring Integration 3.1 or above.
|
||||
</xsd:documentation>
|
||||
<!-- TODO: Revert in the Spring Integration 3.1 or above after removing Jackson 1 backward compatibility
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.support.json.JsonObjectMapper" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>-->
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
|
||||
@@ -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<Message<?>> sameExceptImmutableHeaders(Message<?> operand) {
|
||||
|
||||
@@ -10,12 +10,6 @@
|
||||
<json-to-object-transformer id="defaultJacksonMapperTransformer" input-channel="defaultObjectMapperInput"
|
||||
type="org.springframework.integration.json.TestPerson"/>
|
||||
|
||||
<json-to-object-transformer id="customJacksonMapperTransformer" input-channel="customObjectMapperInput"
|
||||
type="org.springframework.integration.json.TestPerson"
|
||||
object-mapper="customObjectMapper"/>
|
||||
|
||||
<beans:bean id="customObjectMapper" class="org.springframework.integration.json.JsonToObjectTransformerParserTests$CustomObjectMapper"/>
|
||||
|
||||
<json-to-object-transformer id="customJsonMapperTransformer" input-channel="customJsonObjectMapperInput"
|
||||
type="org.springframework.integration.json.TestPerson"
|
||||
object-mapper="customJsonObjectMapper"/>
|
||||
|
||||
@@ -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<String> 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 {
|
||||
|
||||
|
||||
@@ -9,17 +9,15 @@
|
||||
|
||||
<object-to-json-transformer id="defaultTransformer" input-channel="defaultObjectMapperInput"/>
|
||||
|
||||
<object-to-json-transformer id="customTransformer" input-channel="customObjectMapperInput" object-mapper="customObjectMapper"/>
|
||||
|
||||
<object-to-json-transformer id="emptyContentTypeTransformer" input-channel="customObjectMapperInput" content-type=""/>
|
||||
|
||||
<object-to-json-transformer id="overridenContentTypeTransformer" input-channel="customObjectMapperInput" content-type="text/xml"/>
|
||||
|
||||
<beans:bean id="customObjectMapper" class="org.springframework.integration.json.ObjectToJsonTransformerParserTests$CustomObjectMapper"/>
|
||||
|
||||
<object-to-json-transformer id="customJsonObjectMapperTransformer" input-channel="customJsonObjectMapperInput"
|
||||
object-mapper="customJsonObjectMapper"/>
|
||||
|
||||
<object-to-json-transformer id="jsonNodeTransformer" input-channel="jsonNodeInput" result-type="NODE"/>
|
||||
|
||||
<beans:bean id="customJsonObjectMapper" class="org.springframework.integration.json.ObjectToJsonTransformerParserTests$CustomJsonObjectMapper"/>
|
||||
|
||||
</beans:beans>
|
||||
|
||||
@@ -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<TestPerson> 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<TestPerson> 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<Object> {
|
||||
static class CustomJsonObjectMapper extends JsonObjectMapperAdapter<Object, Object> {
|
||||
|
||||
@Override
|
||||
public String toJson(Object value) throws Exception {
|
||||
|
||||
@@ -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 = JacksonJsonObjectMapperProvider.newInstance();
|
||||
|
||||
private volatile Deserializer<byte[]> packetDeserializer = new ByteArrayLfSerializer();
|
||||
|
||||
@@ -59,7 +59,7 @@ public class MapJsonSerializer implements Serializer<Map<?, ?>>, Deserializer<Ma
|
||||
* JSON. Use this if you wish to set additional {@link JsonObjectMapper} implementation features.
|
||||
* @param jsonObjectMapper the jsonObjectMapper.
|
||||
*/
|
||||
public void setJsonObjectMapper(JsonObjectMapper<?> jsonObjectMapper) {
|
||||
public void setJsonObjectMapper(JsonObjectMapper<?, ?> jsonObjectMapper) {
|
||||
Assert.notNull(jsonObjectMapper, "'jsonObjectMapper' cannot be null");
|
||||
this.jsonObjectMapper = jsonObjectMapper;
|
||||
}
|
||||
|
||||
@@ -361,13 +361,23 @@ public class Foo {
|
||||
In addition to JSON Transformers, Spring Integration provides a built-in <emphasis>#jsonPath</emphasis>
|
||||
SpEL function for use in expressions. For more information see <xref linkend="spel"/>.
|
||||
</para>
|
||||
<para>
|
||||
<para id="transformer-xpath-spel-function">
|
||||
<emphasis role="bold">#xpath SpEL Function</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
Since version <emphasis>3.0</emphasis>, Spring Integration also provides a built-in <emphasis>#xpath</emphasis>
|
||||
SpEL function for use in expressions. For more information see <xref linkend="xpath-spel-function"/>.
|
||||
</para>
|
||||
<para>
|
||||
Beginning with <emphasis>version 4.0</emphasis>, the <classname>ObjectToJsonTransformer</classname>
|
||||
supports the <code>resultType</code> property, to specify the <emphasis>node</emphasis> JSON representation.
|
||||
The result node tree representation depends on the implementation of the provided <interfacename>JsonObjectMapper</interfacename>.
|
||||
By default, the <classname>ObjectToJsonTransformer</classname> uses a <classname>Jackson2JsonObjectMapper</classname>
|
||||
and delegates the conversion of the object to the node tree to the <classname>ObjectMapper#valueToTree</classname> method.
|
||||
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"/>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="transformer-annotation">
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<ulink url="https://github.com/spring-projects/spring-integration/wiki/Spring-Integration-3.0-to-4.0-Migration-Guide"
|
||||
>Migration Guide</ulink>.
|
||||
</para>
|
||||
<section id="3.0-xpath-header-enricher-header-type">
|
||||
<section id="4.0-xpath-header-enricher-header-type">
|
||||
<title>Header Type for XPath Header Enricher</title>
|
||||
<para>
|
||||
The <code>header-type</code> attribute has been introduced for the <code>header</code> sub-element of the
|
||||
@@ -41,5 +41,14 @@
|
||||
For more information see <xref linkend="xml-xpath-header-enricher"/>.
|
||||
</para>
|
||||
</section>
|
||||
<section id="4.0-object-to-json-transformer-result-type">
|
||||
<title>Object To Json Transformer: Node Result</title>
|
||||
<para>
|
||||
The <code>result-type</code> attribute has been introduced for the <code><int:object-to-json-transformer></code>.
|
||||
This attribute provides the target type for the result of object mapping to JSON.
|
||||
It supports <code>STRING</code> (default) and <code>NODE</code>.
|
||||
For more information see <xref linkend="transformer-xpath-spel-function"/>.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
Reference in New Issue
Block a user