Подтвердить что ты не робот

Spring Служба REST: как настроить удаление нулевых объектов в json-ответе

У меня есть весенний веб-сервис, который возвращает JSON-ответ. Я использую приведенный здесь пример для создания сервиса: http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/

Формат, в котором возвращается json: { "Имя": нулевой, "staffName": [ "KFC-Kampar", "кузнец"]}

Я хочу удалить все нулевые объекты из возвращенного ответа, чтобы он выглядел так: { "StaffName": [ "KFC-Kampar", "Смит"]}

Я нашел похожие вопросы, задаваемые здесь, но я смог найти решение, работающее, например,

Настройка ObjectMapper в Spring

Как настроить MappingJacksonHttpMessageConverter при использовании конфигурации на основе весенних аннотаций?

настройка jacksonObjectMapper не работает spring MVC 3

как настроить пружинный MVC 3, чтобы он не возвращал "ноль" объект в ответе json?

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, за исключением того, что я закомментировал настройку переменной "Имя магазина", чтобы она была нулевой, т.е.

@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-mapper-asl 1.9.0 и jackson-core-asl 1.9.0. Это единственные новые фляги, которые я добавил в pom в рамках проекта spring-json, который я скачал с mkyong.com.

Проект компилируется успешно, но когда я вызываю сервис через браузер, я все равно получаю то же самое, т.е. { "Имя": нулевой, "staffName": [ "KFC-Kampar", "кузнец"]}

Может кто-нибудь сказать мне, где я не так с моей конфигурации?

Я пробовал несколько других вариантов, но единственный способ вернуть 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, но это решение мне не подходит.

Я не понимаю, почему это работает в коде, но не в конфигурации, поэтому любая помощь будет фантастической.

4b9b3361

Ответ 1

С Jackson 2.0 вы можете использовать JsonInclude

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

Ответ 2

Поскольку Джексон используется, вы должны настроить его как свойство Джексона. В случае служб Spring Boot REST его необходимо настроить в application.properties или application.yml:

spring.jackson.default-property-inclusion = NON_NULL

источник

Ответ 3

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

для Jackson 2.0 или более поздней версии @JsonInclude(Include.NON_NULL)

Это удалит как пустые, так и нулевые объекты.

Ответ 4

Если вы используете 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>

Ответ 5

Начиная с Jackson 2.0, @JsonSerialize(include = xxx) устарел в пользу @JsonInclude

Ответ 6

Начиная с версии 1.6, мы имеем новую аннотацию JsonSerialize (например, в версии 1.9.9).

Пример:

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

Значение по умолчанию ВСЕГДА.

В старых версиях вы можете использовать JsonWriteNullProperties, который устарел в новых версиях. Пример:

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

Ответ 7

Для всех пользователей, не имеющих xml-конфигураций:

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

Ответ 8

Я нашел решение, настроив контейнер 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: с помощью аннотации. Думаю, решение, использующее mvc: annotation-driven и все преимущества, которые его сопровождают, будет намного лучше. Если бы кто-нибудь мог показать мне, как это сделать, это было бы здорово.

Ответ 10

Установка опции 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);
    }
}