如何将Java ZoneDateTime序列化为XML文件

如何将Java ZoneDateTime序列化为XML文件,java,hibernate,serialization,xmlencoder,Java,Hibernate,Serialization,Xmlencoder,序列化ZoneDateTime时出错(它根本不显示在输出xml中): java.lang.实例化异常:java.time.ZoneDateTime 继续 java.lang.RuntimeException:计算失败:=Class.new() 继续 我有一个类的实例,其中一个字段的类型为ZonedDateTime。 当我尝试使用XMLEncoder序列化对象时: import java.beans.XMLEncoder; 我得到这个错误。在输出文件中,除带有ZonedDateTime的字段外,

序列化ZoneDateTime时出错(它根本不显示在输出xml中):

java.lang.实例化异常:java.time.ZoneDateTime

继续

java.lang.RuntimeException:计算失败:=Class.new()

继续

我有一个类的实例,其中一个字段的类型为ZonedDateTime。 当我尝试使用XMLEncoder序列化对象时:

import java.beans.XMLEncoder;
我得到这个错误。在输出文件中,除带有ZonedDateTime的字段外,所有其他字段都会显示

带有ZonedDateTime的字段如下所示,例如:

ZonedDateTime date = ZonedDateTime.parse("2010-01-10T00:00:00Z[CET]");
有没有办法把它转换成可以工作的日期格式? e、 g

上面的编写(使用.toLocalDateTime())可能没有任何意义,但它只是一个示例


实际上,我正在序列化这些对象的整个列表,因此错误出现了很多次(并且在xml文件中始终没有输出)

XMLEncoder和XMLDecoder用于常规JavaBean类。通常,这些类具有公共零参数构造函数和公共属性访问器方法。还有一些对其他类的支持,比如那些具有接受属性值的构造函数的类,但是大多数java.time类是不同的,并且没有对它们的内置支持

幸运的是,您可以为每个计划序列化的非JavaBean类提供自己的支持

因此,第一步是为ZoneDateTime提供PersistenceDelegate:

PersistenceDelegate zonedDateTimeDelegate = new PersistenceDelegate() {
    @Override
    protected Expression instantiate(Object target,
                                     Encoder encoder) {
        ZonedDateTime other = (ZonedDateTime) target;
        return new Expression(other, ZonedDateTime.class, "of",
            new Object[] {
                other.getYear(),
                other.getMonthValue(),
                other.getDayOfMonth(),
                other.getHour(),
                other.getMinute(),
                other.getSecond(),
                other.getNano(),
                other.getZone()
            });
    }
};

encoder.setPersistenceDelegate(
    ZonedDateTime.class, zonedDateTimeDelegate);
但事实证明这是不够的,因为ZoneDateTime的部分也被序列化,其中一个是ZoneId。因此,我们还需要一个用于ZoneId的PersistenceDelegate

PersistenceDelegate很容易编写:

PersistenceDelegate zoneIdDelegate = new PersistenceDelegate() {
    @Override
    protected Expression instantiate(Object target,
                                     Encoder encoder) {
        ZoneId other = (ZoneId) target;
        return new Expression(other, ZoneId.class, "of",
            new Object[] { other.getId() });
    }
};
但注册并不是那么容易<代码>编码器.setPersistenceDelegate(ZoneId.class,zoneIdDelegate)不起作用,因为ZoneId是一个抽象类,这意味着没有ZoneId对象,只有子类的实例。检查PersistenceDelegate时,XMLEncoder不参考继承。要序列化的每个对象的每个类都必须有一个PersistenceDelegate

如果只序列化一个ZoneDateTime,解决方案很简单:

encoder.setPersistenceDelegate(
    date.getZone().getClass(), zoneIdDelegate);
如果有它们的集合,则可以检查它们的所有ZoneId类:

Set<Class<? extends ZoneId>> zoneClasses = new HashSet<>();
for (ZonedDateTime date : dates) {
    Class<? extends ZoneId> zoneClass = date.getZone().getClass();
    if (zoneClasses.add(zoneClass)) {
        encoder.setPersistenceDelegate(zoneClass, zoneIdDelegate);
    }
}

设置
“2010-01-10T00:00:00”
不是
分区日期时间。它没有时区,因此您必须直接将其解析为
LocalDateTime
。为什么不
LocalDateTime.parse(yourString).atZone(ZoneId.of(“CET”))
?在序列化或反序列化过程中是否会出现错误?您的错误表明,它无法使用ZoneDateTime的构造函数实例化ZoneDateTime(这是正确的-它需要调用
parse
方法,并且您可能需要某种类型的适配器用于XML解析器)。但在序列化过程中不会出现此错误,因为在序列化过程中不需要创建实例。@ErwinBolwidt我在尝试序列化(即从程序写入output.xml文件)时遇到此问题。@AndyTurner所以您的意思是:ZonedDateTime日期=LocalDateTime.parse(DateInString).atZone(ZoneId.of(“CET”)?我想我已经试过了,但我会再试一次,当我从一个文件到另一个程序获取信息时,我该如何解码呢?请使用。不需要定制。
Set<Class<? extends ZoneId>> zoneClasses = new HashSet<>();
for (ZonedDateTime date : dates) {
    Class<? extends ZoneId> zoneClass = date.getZone().getClass();
    if (zoneClasses.add(zoneClass)) {
        encoder.setPersistenceDelegate(zoneClass, zoneIdDelegate);
    }
}