Issue
I'm trying to marshal a list: List<Pojo>
objects via the Spring Rest Template.
I can pass along simple Pojo
objects, but I can't find any documentation that describes how to send a List<Pojo>
objects.
Spring is using Jackson JSON to implement the HttpMessageConverter
. The jackson documentation covers this:
In addition to binding to POJOs and "simple" types, there is one additional variant: that of binding to generic (typed) containers. This case requires special handling due to so-called Type Erasure (used by Java to implement generics in somewhat backwards compatible way), which prevents you from using something like
Collection<String>.class
(which does not compile).So if you want to bind data into a
Map<String,User>
you will need to use:
Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() {});
where
TypeReference
is only needed to pass generic type definition (via anynomous inner class in this case): the important part is<Map<String,User>>
which defines type to bind to.
Can this be accomplished in the Spring template? I took a glance at the code and it makes me thing not, but maybe I just don't know some trick.
Solution
The ultimate solution, thanks to the helpful answers below, was to not send a List, but rather send a single object which simply extends a List, such as: class PojoList extends ArrayList<Pojo>
. Spring can successfully marshal this Object, and it accomplishes the same thing as sending a List<Pojo>
, though it be a little less clean of a solution. I also posted a JIRA in spring for them to address this shortcoming in their HttpMessageConverter
interface.
Solution
If I read the docs for MappingJacksonHttpMessageConverter
right, you will have to create and register a subclass of MappingJacksonHttpMessageConverter
and override the getJavaType(Class<?>)
method:
Returns the Jackson JavaType for the specific class. Default implementation returns TypeFactory.type(java.lang.reflect.Type), but this can be overridden in subclasses, to allow for custom generic collection handling. For instance:
protected JavaType getJavaType(Class<?> clazz) {
if (List.class.isAssignableFrom(clazz)) {
return TypeFactory.collectionType(ArrayList.class, MyBean.class);
} else {
return super.getJavaType(clazz);
}
}
Answered By - Sean Patrick Floyd
Answer Checked By - Terry (JavaFixing Volunteer)