Quarkus 3.15中JAXB处理OffsetDateTime反序列化报错如何解决?
问题:Quarkus 3.15中JAXB反序列化XML到含OffsetDateTime的Java对象失败
使用Quarkus 3.15和JAXB将XML字符串反序列化为Java对象时,因对象包含OffsetDateTime类型属性,触发以下错误:
No default constructor found on class java.time.OffsetDateTime: java.lang.NoSuchMethodException: java.time.OffsetDateTime.<init>() at java.base/java.lang.Class.getConstructor0(Class.java:3585) at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2754) at org.glassfish.jaxb.core.v2.ClassFactory.tryGetDeclaredConstructor(ClassFactory.java:109) at org.glassfish.jaxb.core.v2.ClassFactory.create0(ClassFactory.java:78) at org.glassfish.jaxb.runtime.v2.runtime.ClassBeanInfoImpl.createInstance(ClassBeanInfoImpl.java:255) at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:655) at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.StructureLoader.startElement(StructureLoader.java:156) at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:530) at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:509) at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:137) at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:518) at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:183) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:351) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2726) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:542) at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:889) at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:825) at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1224) at java.xml/com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:637) at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:218) at org.glassfish.jaxb.runtime.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:189) at jakarta.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:152) at jakarta.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:205)
对应的Java对象示例:
@XmlRootElement(name="MyXmlPojo") @XmlAccessorType(XmlAccessType.FIELD) public class MyXmlPojo { @XmlElement private String propA = null; @XmlElement private String propB = null; @XmlElement private OffsetDateTime dateProp = null; // 省略其他代码 }
解决方法:自定义JAXB适配器
由于OffsetDateTime无默认构造方法,JAXB无法直接实例化该类型对象,需通过XmlAdapter将其与字符串类型做双向转换:
- 编写适配器类
import jakarta.xml.bind.annotation.adapters.XmlAdapter; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; public class OffsetDateTimeAdapter extends XmlAdapter<String, OffsetDateTime> { // 使用ISO标准时间格式,可根据XML中的时间格式调整 private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_OFFSET_DATE_TIME; @Override public OffsetDateTime unmarshal(String xmlDateTime) throws Exception { return xmlDateTime != null ? OffsetDateTime.parse(xmlDateTime, FORMATTER) : null; } @Override public String marshal(OffsetDateTime dateTime) throws Exception { return dateTime != null ? dateTime.format(FORMATTER) : null; } }
- 在POJO的
OffsetDateTime属性上添加注解,指定使用该适配器
@XmlRootElement(name="MyXmlPojo") @XmlAccessorType(XmlAccessType.FIELD) public class MyXmlPojo { @XmlElement private String propA = null; @XmlElement private String propB = null; @XmlElement @XmlJavaTypeAdapter(OffsetDateTimeAdapter.class) // 添加此注解 private OffsetDateTime dateProp = null; // 省略构造方法、getter/setter等 }
如果XML中的时间格式与ISO_OFFSET_DATE_TIME不符,只需修改适配器中的DateTimeFormatter为对应的格式即可。
内容的提问来源于stack exchange,提问作者Shadowman
相关产品推荐
相关产品推荐

