Frage

I am using the Simple-Framework to do deserialization of an atom feed that I use the Volley library to retrieve. The entries come in the following formats:

<link href="http://www.example.com/story.html" length="35743" type="html" rel="enclosure" title="" />
<link href="http://www.example.com/image.jpeg" length="35743" type="image/jpeg" />

The basic class model for this is as follows:

@Root(strict=false)
public class ItemLink{
    @Attribute
    String href;

    @Attribute
    String length;

    @Attribute
    ContentTypeModel;

}

The type attribute is mapped to an enumeration:

public enum ContentTypeModel {
    html,
    MP4,
    plaintext
}

The items that have the image/jpeg mime type cause errors because they do not exist in the enumeration, however there is an issue with the "/" character which is invalid java syntax. How can I map this type while still using the enumeration? Is it possible to use @Path and then do parsing with an XPath? I'd like to avoid this but if it's the only way then I will use it.

War es hilfreich?

Lösung

Enums are often a bit tricky here, but there's a good solution for it: Implement a Transform.

Here's an example how to do this:

enum ContentTypeModel:

public enum ContentTypeModel
{
    html,
    MP4,
    plaintext,
    image_jpeg // <-- this is new
}

Not much new here, just a value for image/jpeg - you can name those as you like. The combination enum <--> string is done later.

class ContentTypeModelTransform:

Here you implement how the transformation of value --> string and string --> value is done by simple. Btw. if you don't write and just deserialize, you can drop write() implementation. Just implement what you really need.

public class ContentTypeModelTransform implements Transform<ContentTypeModel>
{
    @Override
    public ContentTypeModel read(String value) throws Exception
    {
        // The special case of 'image/jpeg'
        if( value.equalsIgnoreCase("image/jpeg") == true )
        {
            return ContentTypeModel.image_jpeg;
        }
        else // The default case - use enums valueOf()
        {
            return ContentTypeModel.valueOf(value);
        }
    }


    @Override
    public String write(ContentTypeModel value) throws Exception
    {
        // The special case of 'image/jpeg' - same as in read(), but opposite direction
        if( value == ContentTypeModel.image_jpeg ) 
        {
            return "image/jpeg"; 
        }
        else
        {
            return value.toString();
        }
    }

}

This is a very basic implementation, if you run into a long list of values to translate manually, better use a string switch/case (requires java 7+) or something better.

The class ItemLink does not require changes so far, but there's a difference in calling the deserialization:

Setting a Matcher:

You have to set a Matcher that tells Simple what implementation of Transform you want for your enums.

// Create a matcher - it's so small, you can implement it that way ...
final Matcher matcher = new Matcher()
{
    @Override
    public Transform match(Class type) throws Exception
    {
        /*
         * If it's that enum, simple has to use the new transformer
         * instead of the enum default one.
         */
        if( type.equals(ContentTypeModel.class) == true )
        {
            return new ContentTypeModelTransform();
        }

        return null;
    }
};


Serializer ser = new Persister(matcher); // Set matcher in the ctor
// Everything else is as usual
ItemLink il = ser.read(ItemLink.class, xml);

You can implement and set the matcher in many ways, please refer to simples documentation for more information / examples.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top