1

I need to treat the empty string ("") as null in Spring MVC. This because I found that when I edit a form field (with Angular's ng-model) that was originally undefined, then erase it to blank, Angular will send that bean property as empty string. If I don't touch such null value, it won't be sent in the JSON payload and thus treated as null.

I have configured Jackson with the ACCEPT_EMPTY_STRING_AS_NULL_OBJECT DeserializationFeature in my Spring context. Configuration below:

<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <constructor-arg>
        <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
            <property name="featuresToDisable">
                <array>
                    <util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS" />
                </array>
            </property>
            <property name="featuresToEnable">
                <array>
                    <util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT" />
                    <util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.WRITE_ENUMS_USING_TO_STRING" />
                    <util:constant static-field="com.fasterxml.jackson.databind.DeserializationFeature.READ_ENUMS_USING_TO_STRING" />
                    <util:constant static-field="com.fasterxml.jackson.databind.DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT" />
                </array>
            </property>
            <property name="serializationInclusion">
                <util:constant static-field="com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL" />
            </property>
        </bean>
    </constructor-arg>
    <property name="supportedMediaTypes">
        <array>
            <value>application/json</value>
        </array>
    </property>
</bean>

Still, it looks like it decodes empty strings as empty strings rather than null. I have debugged and I could see "" in the payload. Here is a sample from an admin page

{
   "id":"ADMIN.NOTIFIER_SMTP",
   "host":"aa.bb.cc",
   "protocol":"POP",
   "securityProtocol":"PLAIN",
   "username":"", <----- shall be null on server, I don't care about client
   "passwordSet":false
}

Question is: is something wrong in my configuration? How do I tell Jackson to treat empty as null?

usr-local-ΕΨΗΕΛΩΝ
  • 26,101
  • 30
  • 154
  • 305

2 Answers2

1

Jackson will give you null for other objects, but for String it will give empty String.

But you can use a Custom JsonDeserializer to do this:

   class CustomDeserializer extends JsonDeserializer<String> {

@Override
public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
    String node = jsonParser.readValueAs(String.class);
    if (StringUtils.isBlank(node)) {
        return null;
    }
    return node;
}}

In class you have to use it for location field:

class EventBean {
    public Long eventId;
    public String title;

    @JsonDeserialize(using = CustomDeserializer.class)
    public String location;
}
Ilya Khudyakov
  • 301
  • 3
  • 15
Vijendra Kumar Kulhade
  • 2,217
  • 3
  • 15
  • 25
  • 1
    Sorry, using @JsonDeserialize on every property is a terrible approach! I have plenties of `String` properties. Maybe I should promote such deserializer as global... someway – usr-local-ΕΨΗΕΛΩΝ May 16 '16 at 10:02
1

May be you want to write a CustomObjectMapper

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="custom.CustomObjectMapper"/>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

and add above deserializer in it.

Vijendra Kumar Kulhade
  • 2,217
  • 3
  • 15
  • 25