Edit: Since Jackson 2.5.0, you can use DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_EMPTY_OBJECT to resolve your problem.
The solution Bruce provides has a few problems/disadvantages:
- you'll need to duplicate that code for each type you need to deserialize that way
- ObjectMapper should be reused since it caches serializers and deserializers and, thus, is expensive to create. See http://wiki.fasterxml.com/JacksonBestPracticesPerformance
- if your array contains some values, you probably want let jackson to fail deserializing it because it means there was a problem when it got encoded and you should see and fix that asap.
Here is my "generic" solution for that problem:
public abstract class EmptyArrayAsNullDeserializer<T> extends JsonDeserializer<T> {
private final Class<T> clazz;
protected EmptyArrayAsNullDeserializer(Class<T> clazz) {
this.clazz = clazz;
}
@Override
public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);
if (node.isArray() && !node.getElements().hasNext()) {
return null;
}
return oc.treeToValue(node, clazz);
}
}
then you still need to create a custom deserializer for each different type, but that's a lot easier to write and you don't duplicate any logic:
public class Thing2Deserializer extends EmptyArrayAsNullDeserializer<Thing2> {
public Thing2Deserializer() {
super(Thing2.class);
}
}
then you use it as usual:
@JsonDeserialize(using = Thing2Deserializer.class)
If you find a way to get rid of that last step, i.e. implementing 1 custom deserializer per type, I'm all ears ;)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…