SpringREST Service: 如何配置以删除 json 响应中的空对象

我有一个 Spring webservice,它返回一个 json 响应: Http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/

返回 json 的格式是: {“ name”: null,“ staff Name”: [“ kfc-kampar”,“ smith”]}

我想从返回的响应中移除任何 null 对象,这样看起来就像这样: {“工作人员姓名”: [“ kfc-kampar”,“ smith”]}

我在这里发现了类似的问题,但我已经能够得到一个解决方案工作。

在 Spring 中配置 ObjectMapper

如何配置 MappingJacksonHttpMessageConverter 同时使用基于春天注释的配置?

配置 jacksonObjectMapper 在 Spring mvc 3中不工作

如何配置 Spring mvc 3在 json 响应中不返回“ null”对象?

Spring configure@ResponseBody JSON 格式

Jackson + Spring3.0.5自定义对象映射器

通过阅读这些资料和其他资料,我认为实现我想要的最简洁的方法是使用 Spring 3.1和可以在 mvc 注释中配置的消息转换器。 我更新的 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 变量的设置,因此它为 null。

@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 罐子是 Jackson-mapper-asl 1.9.0和 Jackson-core-asl 1.9.0。这些是我在 mkyong.com 下载的 spring-json 项目中提供的唯一新的罐子。

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

有人能告诉我我的配置哪里出错了吗?

我已经尝试了其他几个选项,但是我能够以正确的格式返回 json 的唯一方法是将 Object 映射器添加到 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;
}

现在,如果我调用服务,我得到预期的即。 {“职员姓名”: [“ kfc-kampar”,“ cronin”]}

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

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

157252 次浏览

I've found a solution through configuring the Spring container, but it's still not exactly what I wanted.

I rolled back to Spring 3.0.5, removed and in it's place I changed my config file to:

    <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>

This is of course similar to responses given in other questions e.g.

configuring the jacksonObjectMapper not working in spring mvc 3

The important thing to note is that mvc:annotation-driven and AnnotationMethodHandlerAdapter cannot be used in the same context.

I'm still unable to get it working with Spring 3.1 and mvc:annotation-driven though. A solution that uses mvc:annotation-driven and all the benefits that accompany it would be far better I think. If anyone could show me how to do this, that would be great.

You can use JsonWriteNullProperties for older versions of Jackson.

For Jackson 1.9+, use JsonSerialize.include.

If you are using Jackson 2, the message-converters tag is:

<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>

Since Jackson 2.0 you can use JsonInclude

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

Since version 1.6 we have new annotation JsonSerialize (in version 1.9.9 for example).

Example:

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

Default value is ALWAYS.

In old versions you can use JsonWriteNullProperties, which is deprecated in new versions. Example:

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

As of Jackson 2.0, @JsonSerialize(include = xxx) has been deprecated in favour of @JsonInclude

For all you non-xml config folks:

ObjectMapper objMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
HttpMessageConverter msgConverter = new MappingJackson2HttpMessageConverter(objMapper);
restTemplate.setMessageConverters(Collections.singletonList(msgConverter));
@JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
public class Shop {
//...
}

for jackson 2.0 or later use @JsonInclude(Include.NON_NULL)

This will remove both empty and null Objects.

Since Jackson is being used, you have to configure that as a Jackson property. In the case of Spring Boot REST services, you have to configure it in application.properties or application.yml:

spring.jackson.default-property-inclusion = NON_NULL

source

Setting the spring.jackson.default-property-inclusion=non_null option is the simplest solution and it works well.

However, be careful if you implement WebMvcConfigurer somewhere in your code, then the property solution will not work and you will have to setup NON_NULL serialization in the code as the following:

@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);
}
}