简体   繁体   English

Spring REST Service:如何配置为在JSON响应中删除空对象

[英]Spring REST Service: how to configure to remove null objects in json response

I have a spring webservice that returns a json response. 我有一个春天的Web服务,返回一个JSON响应。 I'm using the example given here to create the service: http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/ 我正在使用此处给出的示例创建服务: http : //www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/

The format the json is returned in is: {"name":null,"staffName":["kfc-kampar","smith"]} 返回json的格式为:{“ name”:null,“ staffName”:[“ kfc-kampar”,“ smith”]}

I want to remove any null objects from the returned response so it looks like this: {"staffName":["kfc-kampar","smith"]} 我想从返回的响应中删除所有空对象,因此它看起来像这样:{“ staffName”:[“ kfc-kampar”,“ smith”]}

I've found similar questions asked here but I've been able to get a solution working eg 我在这里发现了类似的问题,但是我已经找到了解决方案,例如

Configuring ObjectMapper in Spring 在Spring中配置ObjectMapper

How to configure MappingJacksonHttpMessageConverter while using spring annotation-based configuration? 在使用基于Spring注释的配置时如何配置MappingJacksonHttpMessageConverter?

configuring the jacksonObjectMapper not working in spring mvc 3 配置jacksonObjectMapper在Spring MVC 3中不起作用

how to configure spring mvc 3 to not return "null" object in json response? 如何配置Spring MVC 3在JSON响应中不返回“空”对象?

Spring configure @ResponseBody JSON format Spring配置@ResponseBody JSON格式

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

From reading through these and other sources, I figured the cleanest way to achieve what I wanted was to use Spring 3.1 and the message-converters that can be configured within the mvc-annotation. 通过阅读这些和其他资料,我发现实现我想要的最干净的方法是使用Spring 3.1和可以在mvc-annotation中配置的消息转换器。 My updated spring config file is: 我更新的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>

The service class is the same as given on the mkyong.com site, except I commented out the setting of the Shop name variable so it's null ie 服务类与mkyong.com网站上提供的服务类相同,只不过我注释掉了商店名称变量的设置,因此它为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;
    }
}

The Jackson jars I'm using are jackson-mapper-asl 1.9.0 and jackson-core-asl 1.9.0. 我正在使用的Jackson罐子是jackson-mapper-asl 1.9.0和jackson-core-asl 1.9.0。 These are the only new jars I've added to the pom as provided as part of the spring-json project I downloaded from mkyong.com. 这些是我从mkyong.com下载的spring-json项目的一部分,是我添加到pom中的唯一新罐。

The project builds successfully, but when I invoke the service through the browser I still get the same thing ie {"name":null,"staffName":["kfc-kampar","smith"]} 该项目成功构建,但是当我通过浏览器调用服务时,我仍然得到相同的信息,即{“ name”:null,“ staffName”:[“ kfc-kampar”,“ smith”]}

Can anyone tell me where I'm going wrong with my configuration? 谁能告诉我我的配置哪里出问题了?

I've tried several other options, but the only way I've been able to return the json in the correct format is to add the Object mapper to the JSONController and have the "getShopInJSON" method return a string ie 我尝试了其他几种选择,但是我能够以正确格式返回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;
}

Now if I invoke the service I get the expected ie {"staffName":["kfc-kampar","cronin"]} 现在,如果我调用该服务,则会得到预期的结果,即{“ staffName”:[“ kfc-kampar”,“ cronin”]}

I've also been able to get it to work using the @JsonIgnore annotation, but this solution isn't suitable for me. 我还可以使用@JsonIgnore批注使其正常工作,但是该解决方案不适合我。

I don't understand why it's working in code but not in the configuration, so any help would be fantastic. 我不明白为什么它可以在代码中工作,但不能在配置中工作,所以任何帮助都是很棒的。

Since Jackson 2.0 you can use JsonInclude 从Jackson 2.0开始,您可以使用JsonInclude

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

Since Jackson is being used, you have to configure that as a Jackson property. 由于使用了Jackson,因此您必须将其配置为Jackson属性。 In the case of Spring Boot REST services, you have to configure it in application.properties or application.yml : 对于Spring Boot REST服务,您必须在application.propertiesapplication.yml进行配置:

spring.jackson.default-property-inclusion = NON_NULL

source 资源

@JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
public class Shop {
    //...
}

for jackson 2.0 or later use @JsonInclude(Include.NON_NULL) 对于杰克逊2.0或更高版本,请使用@JsonInclude(Include.NON_NULL)

This will remove both empty and null Objects. 这将同时删除空对象和空对象。

If you are using Jackson 2, the message-converters tag is: 如果您使用的是Jackson 2,则消息转换器标签为:

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

从Jackson 2.0开始,不推荐使用@JsonSerialize(include = xxx) ,而推荐使用@JsonInclude

Since version 1.6 we have new annotation JsonSerialize (in version 1.9.9 for example). 从1.6版开始,我们有了新的注释JsonSerialize(例如在1.9.9版中)。

Example: 例:

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

Default value is ALWAYS. 默认值为ALWAYS。

In old versions you can use JsonWriteNullProperties, which is deprecated in new versions. 在旧版本中,可以使用JsonWriteNullProperties,在新版本中已弃用。 Example: 例:

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

For all you non-xml config folks: 对于所有非XML配置人员:

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

I've found a solution through configuring the Spring container, but it's still not exactly what I wanted. 我已经通过配置Spring容器找到了一个解决方案,但是仍然不是我想要的。

I rolled back to Spring 3.0.5, removed and in it's place I changed my config file to: 我回滚到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>

This is of course similar to responses given in other questions eg 当然,这类似于其他问题中的回答,例如

configuring the jacksonObjectMapper not working in spring mvc 3 配置jacksonObjectMapper在Spring MVC 3中不起作用

The important thing to note is that mvc:annotation-driven and AnnotationMethodHandlerAdapter cannot be used in the same context. 需要注意的重要一点是,不能在同一上下文中使用mvc:annotation-driven和AnnotationMethodHandlerAdapter。

I'm still unable to get it working with Spring 3.1 and mvc:annotation-driven though. 我仍然无法在Spring 3.1和mvc:annotation-driven中使用它。 A solution that uses mvc:annotation-driven and all the benefits that accompany it would be far better I think. 我认为,使用mvc:annotation-driven和所有附带好处的解决方案会更好。 If anyone could show me how to do this, that would be great. 如果有人可以告诉我如何做到这一点,那就太好了。

You can use JsonWriteNullProperties for older versions of Jackson. 您可以将JsonWriteNullProperties用于旧版本的Jackson。

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

Setting the spring.jackson.default-property-inclusion=non_null option is the simplest solution and it works well. 设置spring.jackson.default-property-inclusion=non_null选项是最简单的解决方案,并且效果很好。

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: 但是 ,请注意,如果在代码中的某处实现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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM