Wednesday, April 30, 2014

Jackson @Unwrapped with type information

If you are reading this, then it is highly possible that you know that currently Jackson @Unwrapped does not play nice with type information.

 Actually, in my case the issue was only with serialization. Jackson did recognize my type information, embedded as @type property while deserializing. On serialization it produced something like {:{"a":1}}. But I wanted {"@type":"myType", "a":1}.

Jackson has this issue registered in issue tracker, but it looks like correct fix is too complex. But I still want inheritance with unwrapping :) Here is a snippet that fixes issue.

NB! This code snippet fixes issue, but it's global effect is not confirmed :D

public class UwrappedWithTypeInformation {
public static void main(String... args) {
new ObjectMapper().registerModule(new SimpleModule() {
public void setupModule(SetupContext context) {
super.setupModule(context);
context.addBeanSerializerModifier(new BeanSerializerModifier() {
public JsonSerializer<?> modifySerializer(
SerializationConfig config,
BeanDescription beanDesc,
JsonSerializer<?> serializer) {
if (serializer instanceof BeanSerializer) {
return new BeanSerializer((BeanSerializerBase) serializer) {
@Override
public JsonSerializer<Object> unwrappingSerializer(NameTransformer unwrapper) {
return new UnwrappingBeanSerializerWithTypeInformation(this, unwrapper);
}
};
}
return serializer;
}
});
}
});
}
public static class UnwrappingBeanSerializerWithTypeInformation extends UnwrappingBeanSerializer {
public UnwrappingBeanSerializerWithTypeInformation(BeanSerializerBase src, NameTransformer transformer) {
super(src, transformer);
}
@Override
public void serializeWithType(Object bean, JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) throws IOException {
if (_objectIdWriter != null) {
_serializeWithObjectId(bean, jgen, provider, typeSer);
return;
}
jgen.writeStringField(typeSer.getPropertyName(), typeSer.getTypeIdResolver().idFromValue(bean));
if (_propertyFilterId != null) {
serializeFieldsFiltered(bean, jgen, provider);
} else {
serializeFields(bean, jgen, provider);
}
}
}
}

1 comment:

  1. This solution fails, if the nested class uses one of the following features: @JsonIgnoreProperties, @JsonFilter or @JsonIdentityInfo.

    See discussion at
    https://groups.google.com/forum/#!topic/jackson-user/Aw0y6XgToH8

    and the open issue:
    https://github.com/FasterXML/jackson-databind/issues/1427

    Cheers, Paolo

    ReplyDelete