40

想象一下,我在 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);

有没有办法配置这种行为?

我发现了几个相关的问题,但我不确定如何使它们适应我的具体情况:

  1. 带有responsebody的spring prefixjson
  2. 谁在 Spring MVC (@ResponseBody) 中设置响应内容类型

谢谢 !

4

11 回答 11

31

对于使用基于 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>
于 2014-02-13T00:18:37.890 回答
28

我需要解决非常类似的问题,即将 Jackson Mapper 配置为“看在上帝的份上不要序列化空值!!!”。

我不想留下花哨的 mvc:annotation-driven 标签,所以我发现,如何在不删除 mvc:annotation-driven 和添加不太花哨的 ContentNegotiatingViewResolver 的情况下配置 Jackson 的 ObjectMapper。

美妙的是,您不必自己编写任何 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>
于 2012-12-14T10:19:19.453 回答
15

AngerClown为我指明了正确的方向。

这就是我最终所做的,以防万一有人发现它有用。

<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://stackoverflow.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);
于 2011-01-28T17:20:11.517 回答
10

在spring3.2中,引入了新的解决方案:http ://static.springsource.org/spring/docs/3.2.0.BUILD-SNAPSHOT/api/org/springframework/http/converter/json/Jackson2ObjectMapperFactoryBean.html ,下面是我的例子:

 <mvc:annotation-driven>
   ​&lt;mvc:message-converters>
     ​​&lt;bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
       ​​​&lt;property name="objectMapper">
         ​​​​&lt;bean
 class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
           ​​​​​&lt;property name="featuresToEnable">
             ​​​​​​&lt;array>
               ​​​​​​​&lt;util:constant static-field="com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_SINGLE_QUOTES" />
             ​​​​​​&lt;/array>
           ​​​​​&lt;/property>
         ​​​​&lt;/bean>
       ​​​&lt;/property>
     ​​&lt;/bean>
   ​&lt;/mvc:message-converters>
 </mvc:annotation-driven>
于 2013-05-03T07:38:52.703 回答
10

对于 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(...)

于 2015-09-01T07:43:00.517 回答
4

我编写了自己的 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>

于 2012-01-18T21:20:48.093 回答
4

不回答这个问题,但这是谷歌的最高结果。

如果有人来这里并想为 Spring 4 做这件事(就像我发生的那样),你可以使用注释

@JsonInclude(Include.NON_NULL)

在返程班上。

于 2015-01-20T14:50:23.383 回答
2

您可以将 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>

wherecustomObjectMapper在 xml 文件的其他地方定义。请注意,您可以使用 Enums Jackson 定义的方式直接设置 Spring 属性值;看到这个问题

此外,可能不需要 ContentNegotiatingViewResolver,它只是我在现有项目中使用的代码。

于 2011-01-28T00:48:31.280 回答
2

看看 Rick Hightower 的方法。他的方法避免将 ObjectMapper 配置为单例,并允许您针对每个请求方法以不同的方式过滤同一对象的 JSON 响应。

http://www.jroller.com/RickHigh/entry/filtering_json_feeds_from_spring

于 2011-10-13T19:56:50.887 回答
2

您可以执行以下操作(杰克逊版本 < 2):

自定义映射器类:

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>
于 2013-12-25T13:02:10.247 回答
1

是的,但是如果您开始使用 mixins 会发生什么,例如,您不能将 ObjectMapper 作为单例,因为您将在全局范围内应用配置。那么您将在同一个 ObjectMapper 实例上添加或设置 mixin 类吗?

于 2011-02-09T13:53:42.080 回答