Kinorsi Kinorsi - 3 months ago 21
Java Question

Don't return property when it's an empty list with jackson

I have a class need to be dessrialized using jackson and the class has an collection property. The collection is empty, but not null.
Question: How to desersialise the class without empty collection. Sample code below:

class Person
{
String name;
List<Event> events;
//....getter, setter
}


if

person.list = new List<Event>();
persion.name = "hello";


then excepted the json would be:

{name: "hello"}


not

{name: "hello", events:[]}


How to make it? Thank you~~

================================================

I have solved this by n1ckolas's advice. Thank you first.
My jackson version is 2.1.1, and Spring-3.2.2 import better support for this verson of jackson. Also, this works for both arrays and collection.
Below is my configuraion:

<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="objectMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

<!--Json Mapper-->
<bean name="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" autowire="no">
<property name="featuresToDisable">
<list>
<!--not to return empty colletion-->
<value type="com.fasterxml.jackson.databind.SerializationFeature">WRITE_EMPTY_JSON_ARRAYS</value>
</list>
</property>
</bean>

Answer

If you can change your original model with Jackson annotations, here is the way how to achieve this.

Jackson has WRITE_EMPTY_JSON_ARRAYS. And you may turn off it with:

objectMapper.configure(SerializationConfig.Feature.WRITE_EMPTY_JSON_ARRAYS, false);

But it works only for Arrays, but not for Collections. But you may combine @JsonProperty with @JsonIgnore, something like the following:

//....getter, setter of Person class
@JsonIgnore
public List<Event> getEvents() {
    return events;
}

@JsonProperty("events")
public Event[] getEventsArr() {
    return events.toArray(new Event[0]);
}

And afterwards you'll have output, as you expected.

EDIT: If you are using SpringMVC, then you can configure your actual ObjectMapper with explicit reference in mvc:annotation-driven:

<!-- Configures the @Controller programming model -->
<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
            <property name="objectMapper" ref="objectMapper"/>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

<!--custom Json Mapper configuration-->
<bean name="objectMapper" class="org.springframework.http.converter.json.JacksonObjectMapperFactoryBean" autowire="no">
    <property name="featuresToDisable">
        <list>
            <!--Ignore unknown properties-->
            <value type="org.codehaus.jackson.map.SerializationConfig.Feature">WRITE_EMPTY_JSON_ARRAYS</value>
        </list>
    </property>
</bean>

Offtop: usually it's quite useful to specify explicit instance of ObjectMapper, because:

  • you can configure it in the way you want
  • you can use its reference through @Autowired