XMLEncoder 和 XMLDecoder 旨在与常规 Java bean 类一起工作。通常,这些是具有公共零参数构造函数和公共属性访问器方法的类。对其他类有一些支持,例如那些具有获取属性值的构造函数的类,但大多数 java.time 类是不同的,并且没有对它们的内置支持。
幸运的是,您可以通过为您计划序列化的每个非 Java-bean 类指定一个 PersistenceDelegate来提供自己的支持。
因此,第一步是为 ZonedDateTime 提供 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);
但事实证明这还不够,因为 ZonedDateTime 的部分也被序列化,其中之一是 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() });
}
};
但注册它并不容易。encoder.setPersistenceDelegate(ZoneId.class, zoneIdDelegate);
不起作用,因为 ZoneId 是一个抽象类,这意味着没有 ZoneId 对象,只有子类的实例。XMLEncoder 在检查 PersistenceDelegates 时不咨询继承。每个要序列化的对象的每个类都必须有一个 PersistenceDelegate。
如果您只序列化一个 ZonedDateTime,解决方案很简单:
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);
}
}
如果您有包含 ZonedDateTimes 的聚合对象,您可以简单地以类似方式遍历它们并访问这些 ZonedDateTime 值。