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); } }
Advertisement
Answer
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);