Spring / json:转换类似List <mypojo> </mypojo>的类型集合

时间:2011-05-30 06:56:33

标签: java spring collections spring-mvc jackson

我正在尝试通过Spring Rest Template封送列表:List<Pojo>个对象。

我可以传递简单的Pojo个对象,但我找不到任何描述如何发送List<Pojo>个对象的文档。

Spring正在使用Jackson JSON来实现HttpMessageConverter。杰克逊的文档涵盖了这一点:

  

除了绑定到POJO和   “简单”类型,有一个   附加变体:绑定到的变体   通用(类型)容器。这个案例   由于需要特殊处理   所谓的类型擦除(由Java使用)   在某种程度上实现泛型   向后兼容的方式),其中   阻止你使用像   Collection<String>.class(确实如此   不编译)。

     

所以如果你想将数据绑定到   Map<String,User>您将需要使用:

     

Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() {});

     

只需要TypeReference   传递泛型类型定义(通过   在这种情况下任意内部类):   重要的是   <Map<String,User>>定义类型   绑定到。

这可以在Spring模板中完成吗?我瞥了一眼代码,它让我不是,但也许我只是不知道一些技巧。


解决方案

由于下面的有用答案,最终解决方案是不发送List,而是发送一个只扩展List的对象,例如:class PojoList extends ArrayList<Pojo>。 Spring可以成功封送这个Object,它完成了与发送List<Pojo>相同的功能,尽管它不是一个简洁的解决方案。我还在春季发布了一个JIRA,以便他们在HttpMessageConverter界面中解决这个缺点。

3 个答案:

答案 0 :(得分:40)

Spring 3.2中,现在支持使用exchange()上的新RestTemplate - 方法的泛型类型:

 ParameterizedTypeReference<List<MyBean>> typeRef = new ParameterizedTypeReference<List<MyBean>>() {};
 ResponseEntity<List<MyBean>> response = template.exchange("http://example.com", HttpMethod.GET, null, typeRef);

像魅力一样!

答案 1 :(得分:23)

确保包含泛型类型参数的一种方法实际上是子类List或Map类型,这样就可以得到类似的内容:

static class MyStringList extends ArrayList<String> { }

并返回该列表的实例。

那为什么会有所作为呢?因为泛型类型信息仅保留在几个地方:方法和字段声明以及超类型声明。因此,“raw”List不包含任何运行时类型信息,“MyStringList”的类定义通过其超类型声明来实现。 注意,对看似类型化的变量的赋值没有帮助:它只是创建了更多的编译时语法糖:真正的类型信息只传递给类实例(或者lib提供的扩展,如杰克逊的JavaType和TypeReference)。

除此之外,您需要弄清楚如何通过杰克逊JavaTypeTypeReference陪伴价值。

答案 2 :(得分:10)

如果我阅读docs for MappingJacksonHttpMessageConverter权限,则必须创建并注册MappingJacksonHttpMessageConverter的子类并覆盖getJavaType(Class<?>)方法:

  

返回Jackson的Java类型   具体课程。默认实施   回报   TypeFactory.type(java.lang.reflect.Type)   但这可以被覆盖   子类,允许自定义   通用集合处理。对于   实例:

protected JavaType getJavaType(Class<?> clazz) {
   if (List.class.isAssignableFrom(clazz)) {
     return TypeFactory.collectionType(ArrayList.class, MyBean.class);
   } else {
     return super.getJavaType(clazz);
   }
}