Serialize with type only collections in Jackson HttpMessageConverter

Issue: SPR-13318
This commit is contained in:
Sebastien Deleuze
2015-08-13 16:41:48 +02:00
parent 71585c909a
commit 4338719d98
3 changed files with 111 additions and 5 deletions

View File

@@ -258,7 +258,7 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener
else {
objectWriter = this.objectMapper.writer();
}
if (javaType != null) {
if (javaType != null && javaType.isContainerType()) {
objectWriter = objectWriter.withType(javaType);
}
objectWriter.writeValue(generator, value);

View File

@@ -315,8 +315,54 @@ public class MappingJackson2HttpMessageConverterTests {
assertThat(result, not(containsString("\"withoutView\":\"without\"")));
}
@Test // SPR-13318
public void writeSubType() throws Exception {
MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
MyBean bean = new MyBean();
bean.setString("Foo");
bean.setNumber(42);
public static class MyBean {
this.converter.writeInternal(bean, MyInterface.class, outputMessage);
String result = outputMessage.getBodyAsString(Charset.forName("UTF-8"));
assertTrue(result.contains("\"string\":\"Foo\""));
assertTrue(result.contains("\"number\":42"));
}
@Test // SPR-13318
public void writeSubTypeList() throws Exception {
MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
List<MyBean> beans = new ArrayList<MyBean>();
MyBean foo = new MyBean();
foo.setString("Foo");
foo.setNumber(42);
beans.add(foo);
MyBean bar = new MyBean();
bar.setString("Bar");
bar.setNumber(123);
beans.add(bar);
ParameterizedTypeReference<List<MyInterface>> typeReference =
new ParameterizedTypeReference<List<MyInterface>>() {};
this.converter.writeInternal(beans, typeReference.getType(), outputMessage);
String result = outputMessage.getBodyAsString(Charset.forName("UTF-8"));
assertTrue(result.contains("\"string\":\"Foo\""));
assertTrue(result.contains("\"number\":42"));
assertTrue(result.contains("\"string\":\"Bar\""));
assertTrue(result.contains("\"number\":123"));
}
interface MyInterface {
String getString();
void setString(String string);
}
public static class MyBean implements MyInterface {
private String string;

View File

@@ -24,6 +24,7 @@ import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -543,7 +544,7 @@ public class RequestResponseBodyMethodProcessorTests {
@Test // SPR-12811
public void jacksonTypeInfoList() throws Exception {
Method method = JacksonController.class.getMethod("handleList");
Method method = JacksonController.class.getMethod("handleTypeInfoList");
HandlerMethod handlerMethod = new HandlerMethod(new JacksonController(), method);
MethodParameter methodReturnType = handlerMethod.getReturnType();
@@ -551,7 +552,7 @@ public class RequestResponseBodyMethodProcessorTests {
converters.add(new MappingJackson2HttpMessageConverter());
RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(converters);
Object returnValue = new JacksonController().handleList();
Object returnValue = new JacksonController().handleTypeInfoList();
processor.handleReturnValue(returnValue, methodReturnType, this.mavContainer, this.webRequest);
String content = this.servletResponse.getContentAsString();
@@ -559,6 +560,44 @@ public class RequestResponseBodyMethodProcessorTests {
assertTrue(content.contains("\"type\":\"bar\""));
}
@Test // SPR-13318
public void jacksonSubType() throws Exception {
Method method = JacksonController.class.getMethod("handleSubType");
HandlerMethod handlerMethod = new HandlerMethod(new JacksonController(), method);
MethodParameter methodReturnType = handlerMethod.getReturnType();
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(new MappingJackson2HttpMessageConverter());
RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(converters);
Object returnValue = new JacksonController().handleSubType();
processor.handleReturnValue(returnValue, methodReturnType, this.mavContainer, this.webRequest);
String content = this.servletResponse.getContentAsString();
assertTrue(content.contains("\"id\":123"));
assertTrue(content.contains("\"name\":\"foo\""));
}
@Test // SPR-13318
public void jacksonSubTypeList() throws Exception {
Method method = JacksonController.class.getMethod("handleSubTypeList");
HandlerMethod handlerMethod = new HandlerMethod(new JacksonController(), method);
MethodParameter methodReturnType = handlerMethod.getReturnType();
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(new MappingJackson2HttpMessageConverter());
RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(converters);
Object returnValue = new JacksonController().handleSubTypeList();
processor.handleReturnValue(returnValue, methodReturnType, this.mavContainer, this.webRequest);
String content = this.servletResponse.getContentAsString();
assertTrue(content.contains("\"id\":123"));
assertTrue(content.contains("\"name\":\"foo\""));
assertTrue(content.contains("\"id\":456"));
assertTrue(content.contains("\"name\":\"bar\""));
}
String handle(
@RequestBody List<SimpleBean> list,
@@ -774,12 +813,33 @@ public class RequestResponseBodyMethodProcessorTests {
@RequestMapping
@ResponseBody
public List<ParentClass> handleList() {
public List<ParentClass> handleTypeInfoList() {
List<ParentClass> list = new ArrayList<>();
list.add(new Foo("foo"));
list.add(new Bar("bar"));
return list;
}
@RequestMapping
@ResponseBody
public Identifiable handleSubType() {
SimpleBean foo = new SimpleBean();
foo.setId(123L);
foo.setName("foo");
return foo;
}
@RequestMapping
@ResponseBody
public List<Identifiable> handleSubTypeList() {
SimpleBean foo = new SimpleBean();
foo.setId(123L);
foo.setName("foo");
SimpleBean bar = new SimpleBean();
bar.setId(456L);
bar.setName("bar");
return Arrays.asList(foo, bar);
}
}
private static class EmptyRequestBodyAdvice implements RequestBodyAdvice {