81

我有一个返回 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"]}

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

在 Spring 中配置 ObjectMapper

使用基于spring注解的配置时如何配置MappingJacksonHttpMessageConverter?

配置jacksonObjectMapper在spring mvc 3中不起作用

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

Spring配置@ResponseBody JSON格式

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

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

<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 注释让它工作,但这个解决方案不适合我。

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

4

10 回答 10

116

Since Jackson 2.0 you can use JsonInclude

@JsonInclude(Include.NON_NULL)
public class Shop {
    //...
}
于 2014-12-16T20:07:15.687 回答
104

由于正在使用 Jackson,因此您必须将其配置为 Jackson 属性。对于 Spring Boot REST 服务,您必须在application.propertiesor中配置它application.yml

spring.jackson.default-property-inclusion = NON_NULL

资源

于 2016-04-09T09:58:22.753 回答
14
@JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
public class Shop {
    //...
}

杰克逊 2.0 或更高版本使用@JsonInclude(Include.NON_NULL)

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

于 2015-12-31T06:31:04.100 回答
6

设置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);
    }
}
于 2019-08-26T14:55:07.453 回答
5

如果您使用的是 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>
于 2013-10-28T19:36:41.343 回答
5

自 Jackson 2.0 起,@JsonSerialize(include = xxx)已弃用,取而代之的是@JsonInclude

于 2015-10-23T10:14:33.983 回答
4

对于所有非 xml 配置人员:

ObjectMapper objMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
HttpMessageConverter msgConverter = new MappingJackson2HttpMessageConverter(objMapper);
restTemplate.setMessageConverters(Collections.singletonList(msgConverter));
于 2015-12-31T04:53:53.903 回答
3

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

例子:

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

默认值为始终。

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

@JsonWriteNullProperties(false)
public class Test{
    ...
}
于 2015-02-19T09:18:35.903 回答
1

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

对于杰克逊 1.9+,使用JsonSerialize.include.

于 2012-10-04T10:31:19.540 回答
0

我通过配置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>

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

配置jacksonObjectMapper在spring mvc 3中不起作用

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

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

于 2012-10-04T10:17:25.950 回答