I try to deserialize the following json into a java pojo.
[{
"image" : {
"url" : "http://foo.bar"
}
}, {
"image" : "" <-- This is some funky null replacement
}, {
"image" : null <-- This is the expected null value (Never happens in that API for images though)
}]
And my Java classes looks like this:
public class Server {
public Image image;
// lots of other attributes
}
and
public class Image {
public String url;
// few other attributes
}
I use jackson 2.8.6
ObjectMapper.read(json, LIST_OF_SERVER_TYPE_REFERENCE);
but i keep getting the following exception:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of Image: no String-argument constructor/factory method to deserialize from String value ('')
If I add a String setter for it
public void setImage(Image image) {
this.image = image;
}
public void setImage(String value) {
// Ignore
}
I get the following exception
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
The exception does not change whether or not I (also) add a Image setter or not.
I also tried @JsonInclude(NOT_EMPTY)
but this only seems to affect the serialization.
Summary: Some (badly designed) API sends me an empty string (""
) instead of null
and I have to tell Jackson to just ignore that bad value. How can I do this?
There doesn't seem to be a outof the box solution, so i went for the custom deserializer one:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
public class ImageDeserializer extends JsonDeserializer<Image> {
@Override
public Image deserialize(final JsonParser parser, final DeserializationContext context)
throws IOException, JsonProcessingException {
final JsonToken type = parser.currentToken();
switch (type) {
case VALUE_NULL:
return null;
case VALUE_STRING:
return null; // TODO: Should check whether it is empty
case START_OBJECT:
return context.readValue(parser, Image.class);
default:
throw new IllegalArgumentException("Unsupported JsonToken type: " + type);
}
}
}
And use it using the following code
@JsonDeserialize(using = ImageDeserializer.class)
@JsonProperty("image")
public Image image;