How to serialize Java ZonedDateTime to XML file

▼魔方 西西 提交于 2020-02-07 05:28:44

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!