Skip to content
Advertisement

Mapping to “” instead of null Jackson

I have a function that reads XML from a Kafka topic into String format, which I then want to convert to a JSON Object.

Example XML:

<Example>
  <Object>
    <Member1><![CDATA[]]</Member1>
    <Member2><![CDATA[someText]]</Member2>
  </Object>
</Example>

I then have POJO Classes such as: (with lombok getter/setter/toString and jackson annotation imports)

@Getter
@Setter
@ToString
@JacksonXMLRootElement(localName = "Example")
public class TXML {

  @JacksonXmlProperty(localName = "Object")
  private someObject object;
}
@Getter
@Setter
@ToString
public class someObject {

  @JacksonXmlProperty(localName = "Member1")
  private String member1;

  @JacksomXmlProperty(localName = "Member2")
  private String member2;
}

I am then using a MappingJackson2XmlHttpMessageConverter to get an Object Mapper, and using that to map the XML string to an Example class.

@Autowired ObjectMapper xmlMapper;
@Autowired
private MappingJackson2XmlHttpMessageConverter xmlConverter;
...
xmlMapper = xmlConverter.getObjectMapper();
Example example = xmlMapper.readValue(xmlString, Example.class);

This results in an Example Class with the following:

Example
-> object
    -> member1 : ""
    -> member2 : "someText"

I want member1 to be null, instead of an empty string. How can I accomplish this?

Advertisement

Answer

You need to implement your own com.fasterxml.jackson.databind.util.Converter which will convert your value after deserialisation but before setting to required form.

Example implementation:

class CDATAConverter implements Converter<String, String> {

    @Override
    public String convert(String value) {
        return (value == null || value.length() == 0) ? null : value;
    }

    @Override
    public JavaType getInputType(TypeFactory typeFactory) {
        return typeFactory.constructType(String.class);
    }

    @Override
    public JavaType getOutputType(TypeFactory typeFactory) {
        return typeFactory.constructType(String.class);
    }
}

And you need to instruct Jackson to use it:

@Getter
@Setter
@ToString
class SomeObject {

    @JsonDeserialize(converter = CDATAConverter.class)
    @JacksonXmlProperty(localName = "Member1")
    private String member1;

    @JsonDeserialize(converter = CDATAConverter.class)
    @JacksonXmlProperty(localName = "Member2")
    private String member2;
}
Advertisement