views:

1822

answers:

6

Hi I have a Java enum and I want serialize a variable containing an enum value back and forth from XML for persistence. My enum is defined like this...

public enum e_Type
{
 e_Unknown,
 e_Categoric,
 e_Numeric
}

My variable is declared like this...

private e_Type type;

I want it to go into an XML tag like this...

<type>value</type>

What's the best practice for persisting values of enums in XML?

+5  A: 

Try with XStream, it's a library to convert object from and into xml, and support enums too.

String xml = xstream.toXML(enumObject);

http://xstream.codehaus.org/converters.html

Luke
that's a lot of infrastructure just for serialisation of a single value...
Simon
+2  A: 

Another framework is Simple XML Serialization which is similar to C# XML serialization. It can cope with any object graph, including those that contain enums.

Serializer serializer = new Persister();

persister.write(myObject, myOutput);

The serialization of enums uses the final name() method, so that they can always be recovered from XML.

ng
also a lot of infrastructure for such a seemingly simple task. I'm surprised there is no native way. I'll google the final name() thing you refer to here.
Simon
Ya, its simple enough to to Enum.name() and extract it back with Enum.valueOf(Class, String), here just pass in the class of the enum and the value from Enum.name(). And you have recovered the enum from its text format :)
ng
+6  A: 

After getting responses about 3rd party libraries I decided to fix it myself and thought I would post my solution in case anyone else needs to see it. I just added two static methods to the enum that take care of what to send back and forth to XML...

public enum e_Type
{
 e_Unknown,
 e_Categoric,
 e_Numeric;
 public static e_Type type(String token)
 {
  return e_Type.valueOf(token);
 }
 public static String token(e_Type t)
 {
  return t.name();
 }
}

This is a good approach for me because it means I can call my getters and setters with the type() and token() methods during serialisation/deserialisation. I have extended this into all my enums.

I have two main problems with using a 3rd party library for something like this:

  1. Bloat. That's a lot of sledgehammer for my little nut
  2. Dependency. Adding a new 3rd party library means I have to go through licensing and legal checks and ESCROW etc. Really not worth it for 8 lines of code.
Simon
amen - +1 for the simple, easy solution to a narrowly defined problem!
Kevin Day
+4  A: 

have a look at JAXB annotations, which are part of the JDK:

public static void main(String[] args) throws Exception {
    JAXBContext context = JAXBContext.newInstance(Foo.class);
    StringWriter sw = new StringWriter();
    context.createMarshaller().marshal(new Foo(), sw);
    System.out.println(sw);
}

@XmlRootElement
public static class Foo {
    @XmlElement
    private e_Type type = e_Type.e_Unknown;
}

@XmlEnum
public enum e_Type {
    e_Unknown,
    e_Categoric,
    e_Numeric
}

you can customize the output further, e.g. if you wanted your external XML representation to be different from your internal java enum item names:

@XmlEnumValue("UNKNOWN")
e_Unknown

btw: it is a very strong convention to use upper-case names for java classes/enums

netzwerg
A: 

I would second vote for JAXB 2, and XStream is good too. Simple looks a lot like XStream for what that's worth. Also note that use of annotations is optional -- in most cases it can figure out fields and/or methods to use automatically. And you do not need to use XML schemas at all (you can if you want to): many web sites claim you do, but that's wrong (even Simple page claimed something like this).

As to external dependencies: if you are running on JDK 1.6, it comes with bundled implemenation of JAXB (not just the API!). While it is bloat that JDK could do without (since not everyone needs it, those who do could just d/l it IMO), it is nice if you do need it. And implementation is very good, very fast (50-70% speed of just raw XML parsing or writing).

StaxMan
A: 

I like the first approach. There is no need to include third-party libraries for such a simple task. However, making the serialized value == the enum constant literal (i.e. "e_Unknown", "e_Categoric", "e_Numeric") means that if the developer renames the variable names, it makes the stored values unreadable. For example, you save e_Unknown in your XML, later rename the constant as UNKNOWN (for sake of nomenclature). You will then be unable to retrieve old values.

Another approach is to assign each enum a business value, and store the business value in the database, so that rename/refactor of constant names does not break old stored values. I've blogged about this issue if you need more clarification: 3 ways to serialize Java Enums

Vineet Manohar