Jackson 多态序列化生成不正确的 class 名称
Jackson polymorphic serialization generates an incorrect class name
当我使用 Jackson 多态序列化时,它会生成一个 JSON 对象,其完全限定的 class 名称不正确。
下面的代码序列化了一个 XMLGregorianCalendar。输出是:
["java.util.GregorianCalendar",-3600000]
我预期如下:
["javax.xml.datatype.XMLGregorianCalendar",-3600000]
为什么会输出java.util.GregorianCalendar?
或者更重要的是:我该如何解决这个问题?
代码示例:
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);
}
}
为了获得预期的行为,我实现了自定义 XMLGregorianCalendar 序列化程序。 class 负责 XLMGregorianCalendar 的序列化,现在输出正是我所期望的。 :-)
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();
}
}
您可以使用以下代码将此序列化器添加到对象映射器。可以粘贴在问题中的代码示例中。
SimpleModule module = new SimpleModule();
module.addSerializer(XMLGregorianCalendar.class, new XMLGregorianCalendarSerializer());
mapper.registerModule(module);
XML 公历假定单独处理序列化和反序列化。因此,我更喜欢使用以下序列化器和反序列化器:
private class XMLCalendarDeserializer extends StdDeserializer<XMLGregorianCalendar> {
private DatatypeFactory factory = DatatypeFactory.newDefaultInstance();
public XMLCalendarDeserializer() {
super(XMLGregorianCalendar.class);
}
@Override
public XMLGregorianCalendar deserialize(JsonParser parser, DeserializationContext ctx) throws IOException, JsonProcessingException {
if (parser.hasToken(JsonToken.VALUE_STRING)) {
return factory.newXMLGregorianCalendar(parser.getText());
} else {
throw new JsonParseException(parser, "not string token");
}
}
}
private class XMLCalendarSerializer extends StdSerializer<XMLGregorianCalendar> {
public XMLCalendarSerializer() {
super(XMLGregorianCalendar.class);
}
@Override
public void serialize(XMLGregorianCalendar val, JsonGenerator gen, SerializerProvider ser) throws IOException {
gen.writeString(val.toXMLFormat());
}
}
`
当我使用 Jackson 多态序列化时,它会生成一个 JSON 对象,其完全限定的 class 名称不正确。
下面的代码序列化了一个 XMLGregorianCalendar。输出是:
["java.util.GregorianCalendar",-3600000]
我预期如下:
["javax.xml.datatype.XMLGregorianCalendar",-3600000]
为什么会输出java.util.GregorianCalendar?
或者更重要的是:我该如何解决这个问题?
代码示例:
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);
}
}
为了获得预期的行为,我实现了自定义 XMLGregorianCalendar 序列化程序。 class 负责 XLMGregorianCalendar 的序列化,现在输出正是我所期望的。 :-)
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();
}
}
您可以使用以下代码将此序列化器添加到对象映射器。可以粘贴在问题中的代码示例中。
SimpleModule module = new SimpleModule();
module.addSerializer(XMLGregorianCalendar.class, new XMLGregorianCalendarSerializer());
mapper.registerModule(module);
XML 公历假定单独处理序列化和反序列化。因此,我更喜欢使用以下序列化器和反序列化器:
private class XMLCalendarDeserializer extends StdDeserializer<XMLGregorianCalendar> {
private DatatypeFactory factory = DatatypeFactory.newDefaultInstance();
public XMLCalendarDeserializer() {
super(XMLGregorianCalendar.class);
}
@Override
public XMLGregorianCalendar deserialize(JsonParser parser, DeserializationContext ctx) throws IOException, JsonProcessingException {
if (parser.hasToken(JsonToken.VALUE_STRING)) {
return factory.newXMLGregorianCalendar(parser.getText());
} else {
throw new JsonParseException(parser, "not string token");
}
}
}
private class XMLCalendarSerializer extends StdSerializer<XMLGregorianCalendar> {
public XMLCalendarSerializer() {
super(XMLGregorianCalendar.class);
}
@Override
public void serialize(XMLGregorianCalendar val, JsonGenerator gen, SerializerProvider ser) throws IOException {
gen.writeString(val.toXMLFormat());
}
}
`