开发者

Xstream's jodatime Local Date display

I'm using xstrem to serialise a jodatime local date into xml. However when output the generated xml 开发者_开发百科the LocalDate is not in an easily readable format. See below:

<date>
    <iLocalMillis>1316563200000</iLocalMillis>
    <iChronology class="org.joda.time.chrono.ISOChronology" reference="../../tradeDate/iChronology"/>

Any ideas how I can get xstream to display the date in a format that won't drive me up the wall?


Here's what I have used successfully. I believe I used the info at the link mentioned in the first post.

import java.lang.reflect.Constructor;

import org.joda.time.DateTime;

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;


public final class JodaTimeConverter implements Converter {

    @Override
    @SuppressWarnings("unchecked")
    public boolean canConvert(final Class type) {
            return (type != null) && DateTime.class.getPackage().equals(type.getPackage());
    }

    @Override
    public void marshal(final Object source, final HierarchicalStreamWriter writer,
            final MarshallingContext context) {
            writer.setValue(source.toString());
    }

    @Override
    @SuppressWarnings("unchecked")
    public Object unmarshal(final HierarchicalStreamReader reader,
            final UnmarshallingContext context) {
            try {
                    final Class requiredType = context.getRequiredType();
                    final Constructor constructor = requiredType.getConstructor(Object.class);
                    return constructor.newInstance(reader.getValue());
            } catch (final Exception e) {
                throw new RuntimeException(String.format(
                 "Exception while deserializing a Joda Time object: %s", context.getRequiredType().getSimpleName()), e);
            }
    }

}

You can register it like:

XStream xstream = new XStream(new StaxDriver());
xstream.registerConverter(new JodaTimeConverter());


The version from @Ben Carlson has an issue if your object tree contains other classes from the same package as DateTime.

A more robust version for converting DateTime to XML and back that does not require reflection as well:

public static class JodaTimeConverter implements Converter
{
    @Override
    @SuppressWarnings("unchecked")
    public boolean canConvert( final Class type )
    {
        return DateTime.class.isAssignableFrom( type );
    }

    @Override
    public void marshal( Object source, HierarchicalStreamWriter writer, MarshallingContext context )
    {
        writer.setValue( source.toString() );
    }

    @Override
    @SuppressWarnings("unchecked")
    public Object unmarshal( HierarchicalStreamReader reader,
                             UnmarshallingContext context )
    {
        return new DateTime( reader.getValue() );
    }
}

Register the converter with XStream to use it:

XStream xstream = new XStream();
xstream.registerConverter(new JodaTimeConverter());


We needed a to convert a Joda DateTime to / from an XML attribute. For that, converters need to implement interface SingleValueConverter. Our final implementation:

package com.squins.xstream.joda;

import org.joda.time.DateTime;

import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;


public final class JodaDateTimeConverter extends AbstractSingleValueConverter
{

    @Override
    public boolean canConvert(final Class type)
    {
    return DateTime.class.equals(type);
    }

    @Override
    public Object fromString(String str)
    {
    try
    {
        return new DateTime(str);
    }
    catch (final Exception e)
    {
        throw new ConversionException("Cannot parse date " + str);
    }
    }
}


You have to implement (or find) a custom converter for xstream, which will handle JodaTime object in a way you find appropriate.

Here is a small example of such converter: http://x-stream.github.io/converter-tutorial.html


I've used the one that it is here. Pasting it for simplicity:

public class JodaTimeConverter implements Converter
{
    @Override
    public boolean canConvert(Class type) {
        return type != null && DateTime.class.getPackage().equals(type.getPackage());
    }

    @Override
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        writer.setValue(source.toString());
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        try {
            Constructor constructor = context.getRequiredType().getConstructor(Object.class);
            return constructor.newInstance(reader.getValue());
        } catch (Exception e) { // NOSONAR
            throw new SerializationException(String.format(
            "An exception occurred while deserializing a Joda Time object: %s",
            context.getRequiredType().getSimpleName()), e);
        }
    }
}

The other samples didn't work. Cheers!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜