Spring配置@ResponseBody JSON格式
Posted
技术标签:
【中文标题】Spring配置@ResponseBody JSON格式【英文标题】:Spring configure @ResponseBody JSON format 【发布时间】:2011-06-16 22:32:14 【问题描述】:想象一下我在 Spring 3 @Controller 中有这个带注释的方法
@RequestMapping("")
public @ResponseBody MyObject index(@RequestBody OtherObject obj)
MyObject result = ...;
return result;
但是我需要配置输出json格式,就像我在做的那样:
ObjectMapper om = new ObjectMapper();
om.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true);
om.getSerializationConfig()
.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
om.getSerializationConfig()
.set(SerializationConfig.Feature.INDENT_OUTPUT, false);
有没有办法配置这种行为?
我发现了几个相关的问题,但我不确定如何根据我的具体情况调整它们:
-
spring prefixjson with responsebody
Who sets response content-type in Spring MVC (@ResponseBody)
谢谢!
【问题讨论】:
【参考方案1】:对于使用 基于 Java 的 Spring 配置的人:
@Configuration
@ComponentScan(basePackages = "com.domain.sample")
@EnableWebMvc
public class SpringConfig extends WebMvcConfigurerAdapter
....
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
converter.setObjectMapper(objectMapper);
converters.add(converter);
super.configureMessageConverters(converters);
....
我正在使用 MappingJackson2HttpMessageConverter
- 来自 fastxml。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.1</version>
</dependency>
如果你想使用codehaus-jackson映射器,改用这个MappingJacksonHttpMessageConverter
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>$codehaus.jackson.version</version>
</dependency>
【讨论】:
【参考方案2】:我需要解决非常相似的问题,即将 Jackson Mapper 配置为“看在上帝的份上不要序列化空值!!!”。
我不想留下花哨的 mvc:annotation-driven 标签,所以我发现,如何配置 Jackson 的 ObjectMapper,而不删除 mvc:annotation-driven 并添加不是很花哨的 ContentNegotiatingViewResolver。
美妙的是,您不必自己编写任何 Java 代码!
这里是 XML 配置(不要与 Jackson 类的不同命名空间混淆,我只是使用了新的 Jakson 2.x 库......同样适用于 Jackson 1.x 库):
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="serializationInclusion">
<value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
【讨论】:
您还可以利用@Tody.Lu 所指出的Jackson2ObjectMapperFactoryBean
,只需将serializationInclusion
属性设置为NON_NULL
【参考方案3】:
AngerClown pointed me 正确的方向。
这就是我最后所做的,以防万一有人觉得它有用。
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</list>
</property>
</bean>
<!-- jackson configuration : https://***.com/questions/3661769 -->
<bean id="jacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper" />
<bean id="jacksonSerializationConfig" class="org.codehaus.jackson.map.SerializationConfig"
factory-bean="jacksonObjectMapper" factory-method="getSerializationConfig" />
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="jacksonSerializationConfig" />
<property name="targetMethod" value="setSerializationInclusion" />
<property name="arguments">
<list>
<value type="org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion">NON_DEFAULT</value>
</list>
</property>
</bean>
我仍然需要弄清楚如何配置其他属性,例如:
om.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true);
【讨论】:
这对我不起作用。得到这个“org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping:86-AbstractDetectingUrlHandlerMapping.java http-thread-pool-4848-(2) | Rejected bean name 'jacksonObjectMapper': no URL paths known”跨度> 只是不是这不适用于<mvc:annotation-driven />
我发现很难。
AnnotationMethodHandlerAdapter 已弃用.... 改为使用 AbstractHttpMessageConverter
【参考方案4】:
在spring3.2中,引入了新的解决方案:http://static.springsource.org/spring/docs/3.2.0.BUILD-SNAPSHOT/api/org/springframework/http/converter/json/Jackson2ObjectMapperFactoryBean.html, 下面是我的例子:
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean
class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="featuresToEnable">
<array>
<util:constant static-field="com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_SINGLE_QUOTES" />
</array>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
【讨论】:
对我来说,当我在 AbstractMessageConverterMethodProcessor 类中检查 messageConverters 时,它包含两个 MappingJackson2HttpMessageConverter。一个通过 spring 另一个通过我们的配置。 对我来说,当我在 AbstractMessageConverterMethodProcessor 类中检查 messageConverters 时,它包含两个 MappingJackson2HttpMessageConverter。一个通过 spring 另一个通过我们的配置。【参考方案5】:适用于 Spring 4.1.3+ 版
我尝试了 Jama 的解决方案,但随后所有响应都返回了 Content-type 'application/json',包括生成的主要 HTML 页面。
覆盖configureMessageConverters(...)
防止 spring 设置默认转换器。 Spring 4.1.3 允许通过覆盖来修改已配置的转换器 extendMessageConverters(...)
:
@Configuration
public class ConverterConfig extends WebMvcConfigurerAdapter
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters)
for (HttpMessageConverter<?> converter : converters)
if (converter instanceof AbstractJackson2HttpMessageConverter)
AbstractJackson2HttpMessageConverter c = (AbstractJackson2HttpMessageConverter) converter;
ObjectMapper objectMapper = c.getObjectMapper();
objectMapper.setSerializationInclusion(Include.NON_NULL);
super.extendMessageConverters(converters);
见
org.springframework..WebMvcConfigurationSupport#getMessageConverters()
见
org.springframework..WebMvcConfigurationSupport#addDefaultHttpMessageConverters(...)
【讨论】:
【参考方案6】:我编写了自己的 FactoryBean,它实例化了一个 ObjectMapper(简化版):
public class ObjectMapperFactoryBean implements FactoryBean<ObjectMapper>
@Override
public ObjectMapper getObject() throws Exception
ObjectMapper mapper = new ObjectMapper();
mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
return mapper;
@Override
public Class<?> getObjectType()
return ObjectMapper.class;
@Override
public boolean isSingleton()
return true;
以及spring配置中的用法:
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</list>
</property>
</bean>
【讨论】:
【参考方案7】:不回答问题,但这是谷歌搜索结果。
如果有人来这里并想为 Spring 4 做这件事(就像我发生的那样),你可以使用注释
@JsonInclude(Include.NON_NULL)
在返校班上。
【讨论】:
解决了包含非空参数的问题。但是 JsonGenerator.Feature.QUOTE_FIELD_NAMES 或 SerializationConfig.Feature.INDENT_OUTPUT 等其他自定义项呢? QUOTE_FIELD_NAMES 默认启用,因此 spring 4 至少(没有用 3 测试)会自动执行它,它在 javadoc 中:/** *(主要信息).... * 功能是默认启用(因为它是 JSON 规范所要求的)。 */ 至于 INDENT_OUTPUT,你可以这样做: MyObject result = ...; ObjectMapper 映射器 = 新的 ObjectMapper(); return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result);【参考方案8】:您可以将 ObjectMapper 配置为 Spring xml 文件中的 bean。拥有对 ObjectMapper 的引用的是 MappingJacksonJsonView
类。然后,您需要将视图附加到 ViewResolver。
这样的事情应该可以工作:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="html" value="text/html" />
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="prefixJson" value="false" />
<property name="objectMapper" value="customObjectMapper" />
</bean>
</list>
</property>
</bean>
customObjectMapper
在 xml 文件的其他位置定义。请注意,您可以使用 Enums Jackson 定义的方式直接设置 Spring 属性值;见this question。
另外,可能不需要 ContentNegotiatingViewResolver,它只是我在现有项目中使用的代码。
【讨论】:
谢谢,您的回答对我帮助很大。使用最终和工作配置查看我的答案。【参考方案9】:看看 Rick Hightower 的方法。他的方法避免将 ObjectMapper 配置为单例,并允许您针对每个请求方法以不同的方式过滤同一对象的 JSON 响应。
http://www.jroller.com/RickHigh/entry/filtering_json_feeds_from_spring
【讨论】:
有趣。谢谢你,格雷格。 对于其他使用它的人,如果使用 XML 连接通知,请确保它是在 servlet 上下文而不是根上下文中完成的。如果 XML 在根上下文中,则建议不会应用于 @Controllers。 网站已关闭。【参考方案10】:您可以执行以下操作(杰克逊版本
自定义映射器类:
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
public class CustomObjectMapper extends ObjectMapper
public CustomObjectMapper()
super.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true);
super.getSerializationConfig()
.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
super.getSerializationConfig()
.set(SerializationConfig.Feature.INDENT_OUTPUT, false);
弹簧配置:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper">
<bean class="package.CustomObjectMapper"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
【讨论】:
【参考方案11】:是的,但是如果您开始使用 mixins 会发生什么,例如,您不能将 ObjectMapper 作为单例,因为您将在全局范围内应用配置。那么您将在同一个 ObjectMapper 实例上添加或设置 mixin 类?
【讨论】:
好问题。我不知道我采取的方法是否可行。以上是关于Spring配置@ResponseBody JSON格式的主要内容,如果未能解决你的问题,请参考以下文章
Spring @ExceptionHandler 不适用于 @ResponseBody
spring 3.0 @ResponseBody注解返回中文问号乱码解决办法
Spring 4.1.1 RELEASE 和 @ResponseBody 返回 HTTP 406