Serialize with type only collections in Jackson HttpMessageConverter
Issue: SPR-13318
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user