我正在努力解决这个问题:
我们有一个带有Guava多重映射的Table类(简化代码,基本上是1个成员,2个构造函数,多重映射的getter和setter):
public class Table {
private LinkedHashMultimap<String,Field> fields;
public Table(){
this.fields = LinkedHashMultimap.create();
};
public Table (LinkedHashMultimap<String, Field> fields){
this.fields= fields;
}
public LinkedHashMultimap<String, Field> getFields() {
return fields;
}
public void setFields(LinkedHashMultimap<String, Field> fields) {
this.fields = fields;
}
}
我想使用jackson 2.4.3使用Spring MVC 3.2.11进行序列化。
POM相关的依赖关系是:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-guava</artifactId>
<version>2.4.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.11.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.11.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
我的spring.xml 现在看起来像这样(跟随此example)
<bean id="abstractJacksonObjectMapper"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
p:targetMethod="registerModule">
<property name="targetObject">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
p:indentOutput="true">
<!--<property name="featuresToDisable">-->
<!--<util:constant static-field="com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES" />-->
<!--</property>-->
</bean>
</property>
<property name="arguments">
<list>
<bean class="com.fasterxml.jackson.datatype.guava.GuavaModule" />
</list>
</property>
</bean>
<bean id="abstractMappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"
abstract="true"/>
<bean id="abstractMappingJacksonJsonView"
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"
abstract="true"
p:extractValueFromSingleKeyModel="true"/>
<bean id="jacksonObjectMapper" parent="abstractJacksonObjectMapper" />
<bean id="mappingJacksonHttpMessageConverter"
parent="abstractMappingJacksonHttpMessageConverter"
p:objectMapper-ref="jacksonObjectMapper"
p:supportedMediaTypes="application/json" />
<bean id="mappingJacksonJsonView"
parent="abstractMappingJacksonJsonView"
p:objectMapper-ref="jacksonObjectMapper"
p:contentType="application/json" />
我还使用扩展的Jackson2ObjectMapperFactoryBean尝试了另一种方法:
<!-- Json rendering configuration-->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
<property name="objectMapper">
<bean class="my.package.Jackson2ObjectMapperFactoryBean"/>
</property>
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
</bean>
然后FactoryBean看起来像这样:
package my.package;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
public class Jackson2ObjectMapperFactoryBean extends org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean{
public ObjectMapper getObject(){
ObjectMapper objectMapper =super.getObject();
objectMapper.registerModule(new GuavaModule());
return objectMapper;
}
}
我有一个工作正常的Test类,根本没有使用Spring(只测试Table.class + Jackson + guava)简化:
Table study = getTable();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new GuavaModule());
String tableString = mapper.writeValueAsString(table);
它正确地序列化了:
{
"fields":{
"Field1":[
{
"index":0,
"header":"Field1",
"fieldType":"fieldtype",
"description":null,
"cleanHeader":null
}
],
"Field2":[
{
"index":1,
"header":"Field2",
"fieldType":"fieldtype",
"description":null,
"cleanHeader":null
}
]
}
}
使用spring(2种方法中的任何一种)我得到了:
{
"fields":{
"empty": false
}
}
我的控制器有一个@ResponseBody注释,它返回一个表。
编辑:我正在深入调试春季课程(第一次,;-))和org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor 正在处理请求。这与我的问题有关......我的spring xml是否与@ResponseBody注释有些矛盾?
任何想法我做错了什么?
注意:我需要Multimap,不能是标准的Java集合。
答案 0 :(得分:3)
Dunno如果下面的解决方案完全适合您的问题,但是如果您想要将SpringBootApplication配置为序列化番石榴,您可以使用@Configuration
这样增强@Bean
类:
@Configuration
public class Application extends SpringBootServletInitializer {
@Bean
ObjectMapper customizeJacksonConfiguration() {
ObjectMapper om = new ObjectMapper();
om.registerModule(new GuavaModule());
return om;
}
}
答案 1 :(得分:1)
我认为你需要在spring.xml中添加一个mvc:message-converters部分。例如
<mvc:annotation-driven ignoreDefaultModelOnRedirect="true" >
<mvc:message-converters>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
答案 2 :(得分:0)
毕竟我发现@ResponseBody注释强制使用不同的“viewResolver”,即使用Jackson,但没有使用Guava模块。
所以,为了解决这个问题,我在Controller方法中删除了@ResponseBody注释:
<!-- language: java -->
@ResponseBody
@RequestMapping("table")
public Table getTable() {
不幸的是,这是返回:{Table:{...}}并且是由ValueHandlder(ModelAttributeMethodProcessor)引入的人工制品。
最后,现在正在做的是:
1.-恢复@ResponseBody 2.-在MappingJackson2HttpMessageConverter中注册Guava模块,默认情况下使用@ResponseBody处理程序。
这就是spring xml的样子:干净简洁:
<!-- JSON parser configuration-->
<bean id="guavaObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject"><ref local="guavaObjectMapper" /></property>
<property name="targetMethod"><value>registerModule</value></property>
<property name="arguments">
<list>
<bean id="guavaModule" class="com.fasterxml.jackson.datatype.guava.GuavaModule"/>
</list>
</property>
</bean>
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<ref local="guavaObjectMapper"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>