Я десериализирую xml в pojos:
final JaxbAnnotationModule module = new JaxbAnnotationModule();
final PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
.allowIfBaseType(XMLGregorianCalendar.class)
.build();
mapper = new XmlMapper();
mapper.registerModule(module);
mapper.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.NON_CONCRETE_AND_ARRAYS);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
- Поскольку
XMLGregorianCalendar
является абстрактным типом, я добавил PolymorphicTypeValidator
. - Поскольку у меня нет аннотаций Джексона но jaxb аннотации я использую
JaxbAnnotationModule
.
Когда я сейчас пытаюсь десериализовать действительный xml в мое pojo, я получаю следующую ошибку:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_STRING), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class javax.xml.datatype.XMLGregorianCalendar
at [Source: (StringReader); line: 1, column: 1437] (through reference chain: MyObject["date"]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:1627)
at com.fasterxml.jackson.databind.DeserializationContext.reportWrongTokenException(DeserializationContext.java:1377)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._locateTypeId(AsArrayTypeDeserializer.java:141)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:96)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromScalar(AsArrayTypeDeserializer.java:66)
at com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer.deserializeWithType(StdScalarDeserializer.java:26)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:147)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4218)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3214)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3182)
at MyObject.test(MyObject.java:46)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.junit.runner.JUnitCore.run(JUnitCore.java:130)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Я пытался использовать пользовательские десериализаторы, но это не помогло. Есть ли что-то особенное, что мне нужно сделать для XMLGregorianCalendar
? У меня есть другие абстрактные типы, которые работают нормально, используя PolymorphicTypeValidator
EDIT
Ниже приведен POJO, сгенерированный JAXB XJ C:
import org.jvnet.jaxb2_commons.lang.*;
import org.jvnet.jaxb2_commons.locator.ObjectLocator;
import org.jvnet.jaxb2_commons.locator.util.LocatorUtils;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PartialDate", propOrder = {
"date",
"time",
})
public class PartialDate implements Equals2, HashCode2, ToString2 {
@XmlSchemaType(name = "date")
protected XMLGregorianCalendar date;
@XmlSchemaType(name = "time")
protected XMLGregorianCalendar time;
public XMLGregorianCalendar getDate() {
return date;
}
public void setDate(XMLGregorianCalendar value) {
this.date = value;
}
public XMLGregorianCalendar getTime() {
return time;
}
public void setTime(XMLGregorianCalendar value) {
this.time = value;
}
public boolean equals(ObjectLocator thisLocator, ObjectLocator thatLocator, Object object, EqualsStrategy2 strategy) {
if ((object == null) || (this.getClass() != object.getClass())) {
return false;
}
if (this == object) {
return true;
}
final PartialDate that = ((PartialDate) object);
{
XMLGregorianCalendar lhsDate;
lhsDate = this.getDate();
XMLGregorianCalendar lhsTime;
lhsTime = that.getTime();
if (!strategy.equals(LocatorUtils.property(thisLocator, "date", lhsDate), LocatorUtils.property(thatLocator, "date", lhsTime), lhsDate, lhsTime, (this.date != null), (that.date != null))) {
return false;
}
}
{
XMLGregorianCalendar lhsTime;
lhsTime = this.getTime();
XMLGregorianCalendar lhsDate;
lhsDate = that.getDate();
if (!strategy.equals(LocatorUtils.property(thisLocator, "time", lhsTime), LocatorUtils.property(thatLocator, "time", lhsDate), lhsTime, lhsDate, (this.time != null), (that.time != null))) {
return false;
}
}
return true;
}
public boolean equals(Object object) {
final EqualsStrategy2 strategy = JAXBEqualsStrategy.INSTANCE;
return equals(null, null, object, strategy);
}
public int hashCode(ObjectLocator locator, HashCodeStrategy2 strategy) {
int currentHashCode = 1;
{
XMLGregorianCalendar theDate;
theDate = this.getDate();
currentHashCode = strategy.hashCode(LocatorUtils.property(locator, "date", theDate), currentHashCode, theDate, (this.date != null));
}
{
XMLGregorianCalendar theTime;
theTime = this.getTime();
currentHashCode = strategy.hashCode(LocatorUtils.property(locator, "time", theTime), currentHashCode, theTime, (this.time != null));
}
return currentHashCode;
}
public int hashCode() {
final HashCodeStrategy2 strategy = JAXBHashCodeStrategy.INSTANCE;
return this.hashCode(null, strategy);
}
public String toString() {
final ToStringStrategy2 strategy = JAXBToStringStrategy.INSTANCE;
final StringBuilder buffer = new StringBuilder();
append(null, buffer, strategy);
return buffer.toString();
}
public StringBuilder append(ObjectLocator locator, StringBuilder buffer, ToStringStrategy2 strategy) {
strategy.appendStart(locator, this, buffer);
appendFields(locator, buffer, strategy);
strategy.appendEnd(locator, this, buffer);
return buffer;
}
public StringBuilder appendFields(ObjectLocator locator, StringBuilder buffer, ToStringStrategy2 strategy) {
{
XMLGregorianCalendar theDate;
theDate = this.getDate();
strategy.appendField(locator, this, "date", buffer, theDate, (this.date != null));
}
{
XMLGregorianCalendar theTime;
theTime = this.getTime();
strategy.appendField(locator, this, "time", buffer, theTime, (this.time != null));
}
return buffer;
}
}
Мой тест:
@Test
public void canSerializeToXMLAndDeserializeToPOJO() throws DatatypeConfigurationException, JsonProcessingException {
final PartialDate partialDate = new PartialDate();
partialDate.setDate(XMLGregorianCalendar_Test.create());
partialDate.setTime(XMLGregorianCalendar_Test.create());
final String serialized = mapper.writeValueAsString(partialDate);
System.out.println(serialized);
final PartialDate deserialized = mapper.readValue(serialized, PartialDate.class);
assertThat(partialDate).isEqualTo(deserialized);
}
Сериализованный XML:
<PartialDate>
<date>java.util.GregorianCalendar</date>
<date>1585296330000</date>
<time>java.util.GregorianCalendar</time>
<time>1585296330000</time>
</PartialDate>
И при десериализации я получаю сообщение об ошибке выше.
Использование Пользовательский сериализатор, так что XML выглядит так:
<PartialDate>
<date>javax.xml.datatype.XMLGregorianCalendar</date>
<date>1585296330000</date>
<time>javax.xml.datatype.XMLGregorianCalendar</time>
<time>1585296330000</time>
</PartialDate>
выдает ту же ошибку.