问题
Error while serializing ZonedDateTime (it doesn't appear in the output xml at all):
java.lang.InstantiationException: java.time.ZonedDateTime
Continuing ...
java.lang.RuntimeException: failed to evaluate: =Class.new();
Continuing ...
I have an instance of the class, where one of the fields is of a type ZonedDateTime. When i'm trying to serialize the object with XMLEncoder:
import java.beans.XMLEncoder;
I get this errors. In the output file all the other fields appear except the field with ZonedDateTime
this field with ZonedDateTime looks like this e.g.:
ZonedDateTime date = ZonedDateTime.parse("2010-01-10T00:00:00Z[CET]");
Is there a way to convert it to such date format that it will work? e.g.
ZonedDateTime.parse("2010-01-10T00:00:00").toLocalDateTime().atZone(ZoneId.of("CET")
The above writing (with .toLocalDateTime()) may not make any sense, but it's just the example.
I'm actually serializing the whole list of these objects, so the error appears many times (and always no output in xml file)
回答1:
XMLEncoder and XMLDecoder are meant to work with regular Java bean classes. Typically, these are classes which have a public zero-argument constructor and public property accessor methods. There is some support for other classes, such as those with constructors that take property values, but most java.time classes are different and there is no built-in support for them.
Fortunately, you can provide your own support, by specifying a PersistenceDelegate for each non-Java-bean class you plan to serialize.
So, the first step is providing a PersistenceDelegate for ZonedDateTime:
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);
But it turns out this is not enough, because the parts of the ZonedDateTime also get serialized, and one of them is a ZoneId. So we also need a PersistenceDelegate for ZoneId.
That PersistenceDelegate is easy to write:
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() });
}
};
But registering it is not as easy. encoder.setPersistenceDelegate(ZoneId.class, zoneIdDelegate);
won’t work, because ZoneId is an abstract class, which means there are no ZoneId objects, only instances of subclasses. XMLEncoder does not consult inheritance when checking for PersistenceDelegates. There must be a PersistenceDelegate for each class of every object to be serialized.
If you’re only serializing one ZonedDateTime, the solution is easy:
encoder.setPersistenceDelegate(
date.getZone().getClass(), zoneIdDelegate);
If you have a collection of them, you can check all of their ZoneId classes:
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);
}
}
If you have aggregate objects containing ZonedDateTimes, you can simply iterate through them in a similar manner and access those ZonedDateTime values.
来源:https://stackoverflow.com/questions/58809573/how-to-serialize-java-zoneddatetime-to-xml-file