When I use Jackson polymorphic serialization, it generates a JSON object with an incorrect fully qualified class name.
The code below serializes an XMLGregorianCalendar. The output is:
["java.util.GregorianCalendar",-3600000]
I expected the following:
["javax.xml.datatype.XMLGregorianCalendar",-3600000]
Why does it output java.util.GregorianCalendar?
Or more importantly: How do I fix this?
Code example:
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.io.ByteArrayOutputStream;
public class JacksonGregorianProblem {
public static void main(String[] args) throws java.io.IOException, DatatypeConfigurationException {
XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar();
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mapper.writeValue(byteArrayOutputStream, xmlGregorianCalendar);
System.out.println(byteArrayOutputStream);
}
}
To get the expected behavior I have implemented a custom XMLGregorianCalendar serializer. This class takes care of the serialization of the XLMGregorianCalendar and now the output is exactly what I expect. :-)
class XMLGregorianCalendarSerializer extends StdSerializer<XMLGregorianCalendar> {
public XMLGregorianCalendarSerializer() {
this(null);
}
public XMLGregorianCalendarSerializer(Class<XMLGregorianCalendar> t) {
super(t);
}
@Override
public void serialize(XMLGregorianCalendar value, JsonGenerator gen, SerializerProvider provider)
throws IOException
{
gen.writeNumber(value.toGregorianCalendar().getTimeInMillis());
}
@Override
public void serializeWithType(XMLGregorianCalendar value, JsonGenerator gen, SerializerProvider provider,
TypeSerializer typeSerializer) throws IOException
{
gen.writeStartArray();
gen.writeString("javax.xml.datatype.XMLGregorianCalendar");
serialize(value, gen, provider); // call your customized serialize method
gen.writeEndArray();
}
}
You can add this serializer to the object mapper with the code below. It can be pasted in the code example in the question.
SimpleModule module = new SimpleModule();
module.addSerializer(XMLGregorianCalendar.class, new XMLGregorianCalendarSerializer());
mapper.registerModule(module);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With