Support generics in the JsonToObjectTransformer (#2819)
* Support generics in the `JsonToObjectTransformer` * Deprecate `JsonObjectMapperAdapter` if favor of `default` methods in the `JsonObjectMapper` * Introduce `JsonObjectMapper.fromJson(Object, ResolvableType)` to support generics during deserialization * Add `JsonHeaders.RESOLVABLE_TYPE` header handling for the `ResolvableType` management * Add `ResolvableType` argument into the `JsonToObjectTransformer` * Change the `JsonToObjectTransformer` logic to consult request message headers first * Add `ResolvableType`-based factory method into the `Transformers` * Document the change * * Use `0` for conversion to array for headers to remove in the `JsonToObjectTransformer`
This commit is contained in:
committed by
Gary Russell
parent
8f86ef918c
commit
5421574ef5
@@ -23,11 +23,11 @@ import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.ResolvableType;
|
||||
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.JsonObjectMapper;
|
||||
import org.springframework.integration.support.json.JsonObjectMapperAdapter;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
@@ -104,12 +104,18 @@ public class JsonToObjectTransformerParserTests {
|
||||
assertThat(result.getJson()).isEqualTo(jsonString);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
static class CustomJsonObjectMapper extends JsonObjectMapperAdapter {
|
||||
static class CustomJsonObjectMapper implements JsonObjectMapper<Object, Object> {
|
||||
|
||||
@Override
|
||||
public Object fromJson(Object json, Class valueType) {
|
||||
return new TestJsonContainer((String) json);
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromJson(Object json, Class<T> valueType) {
|
||||
return (T) new TestJsonContainer((String) json);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromJson(Object json, ResolvableType valueType) {
|
||||
return (T) new TestJsonContainer((String) json);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,8 +18,12 @@ package org.springframework.integration.json;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.integration.support.json.Jackson2JsonObjectMapper;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
@@ -31,24 +35,36 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class JsonToObjectTransformerTests {
|
||||
|
||||
@Test
|
||||
public void objectPayload() {
|
||||
JsonToObjectTransformer transformer = new JsonToObjectTransformer(TestPerson.class);
|
||||
JsonToObjectTransformer transformer =
|
||||
new JsonToObjectTransformer(
|
||||
ResolvableType.forType(new ParameterizedTypeReference<List<TestPerson>>() { }));
|
||||
// Since DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES is disabled by default
|
||||
// (see Jackson2JsonObjectMapper)
|
||||
// the extra "foo" property is ignored.
|
||||
String jsonString = "{\"firstName\":\"John\",\"lastName\":\"Doe\",\"age\":42," +
|
||||
"\"address\":{\"number\":123,\"street\":\"Main Street\"}, \"foo\":\"bar\"}";
|
||||
String jsonString = "[{\"firstName\":\"John\",\"lastName\":\"Doe\",\"age\":42," +
|
||||
"\"address\":{\"number\":123,\"street\":\"Main Street\"}, \"foo\":\"bar\"}]";
|
||||
Message<?> message = transformer.transform(new GenericMessage<>(jsonString));
|
||||
TestPerson person = (TestPerson) message.getPayload();
|
||||
assertThat(person.getFirstName()).isEqualTo("John");
|
||||
assertThat(person.getLastName()).isEqualTo("Doe");
|
||||
assertThat(person.getAge()).isEqualTo(42);
|
||||
assertThat(person.getAddress().toString()).isEqualTo("123 Main Street");
|
||||
assertThat(message)
|
||||
.extracting(Message::getPayload)
|
||||
.isInstanceOf(List.class)
|
||||
.asList()
|
||||
.hasSize(1)
|
||||
.element(0)
|
||||
.isInstanceOf(TestPerson.class)
|
||||
.satisfies((actual) -> {
|
||||
TestPerson bean = (TestPerson) actual;
|
||||
assertThat(bean).extracting(TestPerson::getFirstName).isEqualTo("John");
|
||||
assertThat(bean).extracting(TestPerson::getLastName).isEqualTo("Doe");
|
||||
assertThat(bean).extracting(TestPerson::getAge).isEqualTo(42);
|
||||
assertThat(bean).extracting(TestPerson::getAddress).asString().isEqualTo("123 Main Street");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.support.DefaultMessageBuilderFactory;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.support.json.Jackson2JsonObjectMapper;
|
||||
import org.springframework.integration.support.json.JsonObjectMapperAdapter;
|
||||
import org.springframework.integration.support.json.JsonObjectMapper;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
@@ -174,7 +174,7 @@ public class ObjectToJsonTransformerParserTests {
|
||||
assertThat(expression.getValue(evaluationContext, payload, Boolean.class)).isTrue();
|
||||
}
|
||||
|
||||
static class CustomJsonObjectMapper extends JsonObjectMapperAdapter<Object, Object> {
|
||||
static class CustomJsonObjectMapper implements JsonObjectMapper<Object, Object> {
|
||||
|
||||
@Override
|
||||
public String toJson(Object value) {
|
||||
|
||||
@@ -183,11 +183,11 @@ public class ObjectToJsonTransformerTests {
|
||||
List<String> list = Collections.singletonList(null);
|
||||
Message<?> out = transformer.transform(new GenericMessage<>(list));
|
||||
assertThat(out.getHeaders().get(JsonHeaders.TYPE_ID).toString()).contains("SingletonList");
|
||||
assertThat(out.getHeaders().get(JsonHeaders.CONTENT_TYPE_ID)).isEqualTo(Object.class);
|
||||
assertThat(out.getHeaders()).doesNotContainKey(JsonHeaders.CONTENT_TYPE_ID);
|
||||
Map<String, String> map = Collections.singletonMap("foo", null);
|
||||
out = transformer.transform(new GenericMessage<>(map));
|
||||
assertThat(out.getHeaders().get(JsonHeaders.TYPE_ID).toString()).contains("SingletonMap");
|
||||
assertThat(out.getHeaders().get(JsonHeaders.CONTENT_TYPE_ID)).isEqualTo(Object.class);
|
||||
assertThat(out.getHeaders()).doesNotContainKey(JsonHeaders.CONTENT_TYPE_ID);
|
||||
assertThat(out.getHeaders().get(JsonHeaders.KEY_TYPE_ID)).isEqualTo(String.class);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user