【问题标题】:Spring REST Service: how to configure to remove null objects in json responseSpring REST 服务:如何配置以删除 json 响应中的空对象
【发布时间】:2012-09-24 07:15:49
【问题描述】:

我有一个返回 json 响应的 spring webservice。我正在使用此处给出的示例来创建服务: http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/

json 返回的格式为: {"name":null,"staffName":["kfc-kampar","smith"]}

我想从返回的响应中删除任何空对象,所以它看起来像这样: {"staffName":["kfc-kampar","smith"]}

我在这里发现了类似的问题,但我已经能够得到一个有效的解决方案,例如

Configuring ObjectMapper in Spring

How to configure MappingJacksonHttpMessageConverter while using spring annotation-based configuration?

configuring the jacksonObjectMapper not working in spring mvc 3

how to configure spring mvc 3 to not return "null" object in json response?

Spring configure @ResponseBody JSON format

Jackson+Spring3.0.5 custom object mapper

通过阅读这些和其他来源,我发现实现我想要的最简洁的方法是使用 Spring 3.1 和可以在 mvc-annotation 中配置的消息转换器。 我更新的 spring 配置文件是:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans     
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

<context:component-scan base-package="com.mkyong.common.controller" />

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
            <property name="prefixJson" value="true" />
            <property name="supportedMediaTypes" value="application/json" />
            <property name="objectMapper">
                <bean class="org.codehaus.jackson.map.ObjectMapper">
                    <property name="serializationInclusion" value="NON_NULL"/>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

服务类与 mkyong.com 网站上给出的相同,只是我注释掉了 Shop name 变量的设置,因此它为空,即

@Controller
@RequestMapping("/kfc/brands")
public class JSONController {
    @RequestMapping(value="{name}", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK) 
    public @ResponseBody Shop getShopInJSON(@PathVariable String name) {
        Shop shop = new Shop();
        //shop.setName(name);
        shop.setStaffName(new String[]{name, "cronin"});
        return shop;
    }
}

我使用的 Jackson jar 是 jackson-mapper-asl 1.9.0 和 jackson-core-asl 1.9.0。这些是我添加到 pom 中的唯一新 jar,作为我从 mkyong.com 下载的 spring-json 项目的一部分提供。

项目构建成功,但是当我通过浏览器调用服务时,我仍然得到相同的结果,即 {"name":null,"staffName":["kfc-kampar","smith"]}

谁能告诉我我的配置哪里出了问题?

我尝试了其他几个选项,但我能够以正确格式返回 json 的唯一方法是将对象映射器添加到 JSONController 并让“getShopInJSON”方法返回一个字符串,即

public @ResponseBody String getShopInJSON(@PathVariable String name) throws JsonGenerationException, JsonMappingException, IOException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);

    Shop shop = new Shop();
    //shop.setName(name);
    shop.setStaffName(new String[]{name, "cronin"});
    String test = mapper.writeValueAsString(shop);
    return test;
}

现在,如果我调用该服务,我会得到预期的结果,即 {"staffName":["kfc-kampar","cronin"]}

我也可以使用 @JsonIgnore 注释让它工作,但这个解决方案不适合我。

我不明白为什么它在代码中而不是在配置中工作,所以任何帮助都会很棒。

【问题讨论】:

  • 对我来说似乎 spring 没有使用 contex 文件中定义的映射器对象,我检查了调试 spring 正在为 xml 中定义的映射器对象调用 setSerializationInclusion() 方法
  • 是的,我也是这么理解的。对象映射器似乎配置正确,只是没有在 spring 容器中使用。

标签: java spring jackson


【解决方案1】:

设置spring.jackson.default-property-inclusion=non_null 选项是最简单的解决方案,而且效果很好。

但是,如果您在代码中的某处实现 WebMvcConfigurer,请注意,属性解决方案将不起作用,您必须在代码中设置 NON_NULL 序列化,如下所示:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    // some of your config here...

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(objectMapper);
        converters.add(jsonConverter);
    }
}

【讨论】:

  • 感谢您提及实现 WebMvcConfigurer 时对属性的影响。它解决了我的问题。
【解决方案2】:

由于使用的是 Jackson,您必须将其配置为 Jackson 属性。对于 Spring Boot REST 服务,你必须在 application.propertiesapplication.yml 中进行配置:

spring.jackson.default-property-inclusion = NON_NULL

source

【讨论】:

  • 不幸的是,版主删除了我的回答,声称这些是重复的问题。但他是一个 Python 人,可能看不出这些是不同的 Java Spring 问题(一个针对 Spring MVC,另一个针对 Spring REST)。他删除了最重要的问题。顺便说一句,没有办法剪裁。答案是一样的。图书馆是一样的(杰克逊)。我会再试一次,以帮助社区。​​span>
  • 属性名称已更改为spring.jackson.default-property-inclusion=NON_NULL。工作正常!
  • 酷,我一直在找这个。无需更改所有 POJO 并将其放在一处。感谢您节省了我的时间!
【解决方案3】:
@JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
public class Shop {
    //...
}

对于 jackson 2.0 或更高版本,请使用 @JsonInclude(Include.NON_NULL)

这将删除空对象和空对象。

【讨论】:

  • @Deprecated // since 2.0, marked deprecated in 2.6
【解决方案4】:

对于所有非 xml 配置人员:

ObjectMapper objMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
HttpMessageConverter msgConverter = new MappingJackson2HttpMessageConverter(objMapper);
restTemplate.setMessageConverters(Collections.singletonList(msgConverter));

【讨论】:

    【解决方案5】:

    从 Jackson 2.0 开始,@JsonSerialize(include = xxx) 已被弃用,取而代之的是 @JsonInclude

    【讨论】:

      【解决方案6】:

      从 1.6 版开始,我们有了新的注释 JsonSerialize(例如在 1.9.9 版中)。

      例子:

      @JsonSerialize(include=Inclusion.NON_NULL)
      public class Test{
      ...
      }
      

      默认值为 ALWAYS。

      在旧版本中,您可以使用 JsonWriteNullProperties,它在新版本中已被弃用。 示例:

      @JsonWriteNullProperties(false)
      public class Test{
          ...
      }
      

      【讨论】:

      • @JsonSerialize(include=Inclusion.NON_NULL) 已弃用
      【解决方案7】:

      从 Jackson 2.0 开始你可以使用JsonInclude

      @JsonInclude(Include.NON_NULL)
      public class Shop {
          //...
      }
      

      【讨论】:

      • 这就是我想要的。谢谢
      【解决方案8】:

      如果您使用的是 Jackson 2,则 message-converters 标签为:

      <mvc:annotation-driven>
          <mvc:message-converters>
              <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                  <property name="prefixJson" value="true"/>
                  <property name="supportedMediaTypes" value="application/json"/>
                  <property name="objectMapper">
                      <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                          <property name="serializationInclusion" value="NON_NULL"/>
                      </bean>
                  </property>
              </bean>
          </mvc:message-converters>
      </mvc:annotation-driven>
      

      【讨论】:

        【解决方案9】:

        您可以将 JsonWriteNullProperties 用于较旧版本的 Jackson。

        对于 Jackson 1.9+,请使用 JsonSerialize.include

        【讨论】:

          【解决方案10】:

          我通过配置Spring容器找到了解决方案,但仍然不是我想要的。

          我回滚到 Spring 3.0.5,删除并在它的位置我将我的配置文件更改为:

              <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>
          
          
          <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_NULL</value>
                  </list>
              </property>
          </bean>
          

          这当然类似于其他问题中给出的回答,例如

          configuring the jacksonObjectMapper not working in spring mvc 3

          需要注意的重要一点是,mvc:annotation-driven 和 AnnotationMethodHandlerAdapter 不能在同一个上下文中使用。

          我仍然无法让它与 Spring 3.1 和 mvc:annotation-driven 一起使用。我认为使用 mvc:annotation-driven 以及伴随它的所有好处的解决方案会好得多。如果有人能告诉我如何做到这一点,那就太好了。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-11-10
            • 2014-08-23
            • 2014-12-31
            • 1970-01-01
            • 2018-01-11
            • 2011-08-28
            • 2011-09-28
            相关资源
            最近更新 更多