2

How to build a converter for the org.simpleframework.xml libary?

I am using the Simple XML Serialization library (org.simpleframework.xml package) from SimpleFramework.org.

I want Joda-Time DateTime objects to be serialized as an ISO 8601 string such as 2014-07-16T00:20:36Z. Upon re-constituting the Java object, I want a DateTime to be constructed from that string. The documentation does not really explain how to build a converter.

I know it has something to do with a Transform and a Matcher. In the MythTV-Service-API project, I found implementations of both Transform and Matcher. But I have not determined how to put it together.

bwt
  • 17,292
  • 1
  • 42
  • 60
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154

1 Answers1

2

You may choose between two approaches, as discussed in this similar Question, Serialization third-party classes with Simple XML (org.simpleframework.xml):

  • Converter
  • Transform

I do not know the pros and cons of each in comparison. But I do know how to implement the Transform approach. For that, read on.

Transform Approach

Three pieces are needed:

  1. An implementation of the Transform interface.
  2. An implementation of the Matcher interface.
  3. A RegistryMatcher instance where the Transform implementation is mapped to the data-type it handles.

All three of these are a part of the transform package.

I suggest putting your implementations in a "converters" package in your project.

Transform Implementation

Your Transform implementation may look like this.

This implementation here is a simplistic. It assumes you want the output to be the default ISO 8601 string generated by a DateTime’s toString method. And it assumes every text input will be compatible with the default parser in a DateTime constructor. To handle other formats, define a bunch of DateTimeFormatter instances, calling the parseDateTime method on each one in succession until a formatter succeeds without throwing an IllegalArgumentException. Another thing to consider is time zone; you may want to force the time zone to UTC or some such.

package com.your.package.converters.simplexml;

import org.joda.time.DateTime;
import org.simpleframework.xml.transform.Transform;
import org.slf4j.LoggerFactory;

/**
 *
 * © 2014 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for such usage and its consequences.
 */
public class JodaTimeDateTimeTransform implements Transform<DateTime>
{
    //static final org.slf4j.Logger logger = LoggerFactory.getLogger( JodaTimeDateTimeTransform.class );

    @Override
    public DateTime read ( String input ) throws Exception
    {
        DateTime dateTime = null;
        try {
            dateTime = new DateTime( input );  // Keeping whatever offset is included. Not forcing to UTC.
        } catch ( Exception e ) {
            //logger.debug( "Joda-Time DateTime Transform failed. Exception: " + e );
        }
        return dateTime;
    }

    @Override
    public String write ( DateTime dateTime ) throws Exception
    {
        String output = dateTime.toString();  // Keeping whatever offset is included. Not forcing to UTC.
        return output;
    }

}

Matcher Implementation

The Matcher implementation is quick and easy.

 package com.your.package.converters.simplexml;

import org.simpleframework.xml.transform.Transform;
import org.simpleframework.xml.transform.Matcher;

/**
 *
 * © 2014 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for such usage and its consequences.
 */
public class JodaTimeDateTimeMatcher implements Matcher
{
    @Override
    public Transform match ( Class classType ) throws Exception
    {
        // Is DateTime a superclass (or same class) the classType?
        if ( org.joda.time.DateTime.class.isAssignableFrom( classType ) ) {
            return new JodaTimeDateTimeTransform();
        }
        return null;
    }
}

Registry

Putting these into action means the use of a registry.

RegistryMatcher matchers = new RegistryMatcher();
matchers.bind( org.joda.time.DateTime.class , JodaTimeDateTimeTransform.class );
// You could add other data-type handlers, such as the "YearMonth" class in Joda-Time.
//matchers.bind( org.joda.time.YearMonth.class , JodaTimeYearMonthTransform.class );

Strategy strategy = new AnnotationStrategy();
Serializer serializer = new Persister( strategy , matchers );

And continue on the usual way with a serializer that understands the Joda-Time type(s).

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154