views:

202

answers:

2

I am trying out the Simple XML serializer. I am more interested in deserialization from XML->Java. Here is my code as a unit test:

import java.io.StringReader;
import java.io.StringWriter;

import junit.framework.TestCase;

import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

public class SimpleTest extends TestCase {
    public void testWriting() throws Exception {
     StringWriter writer = new StringWriter();
     Address address = new Address("1234 Main Street", "San Francisco", "CA");
     Serializer serializer = new Persister();

     serializer.write(address, writer);
     System.out.println("Wrote: " + writer.getBuffer());
    }

    public void testReading() throws Exception {
     String input = "<address street='1234 Main Street' city='San Francisco' state='CA'/>";
     Serializer serializer = new Persister();
     System.out.println("Read back: " + serializer.read(Address.class, new StringReader(input)));
    }
}

@Root
class Address {
    @Attribute(name="street")
    private final String street;

    @Attribute(name="city")
    private final String city;

    @Attribute(name="state")
    private final String state;

    public Address(@Attribute(name="street") String street, @Attribute(name="city") String city, @Attribute(name="state") String state) {
     super();
     this.street = street;
     this.city = city;
     this.state = state;
    }

    @Override
    public String toString() {
     return "Address [city=" + city + ", state=" + state + ", street=" + street + "]";
    } 
}

This works, but the repeated @Attribute annotations (at the field and at the constructor argument) in the Address class look ugly. Is there some way to:

  • have simple figure out the attribute name from the field name?
  • have simple ignore serialization, so that I can get away with annotating either the fields or the constructor argument?
A: 

I don't think you need all that repetition and the extra annotations' attribute. If the name is the same as the object attribute, it will be used by default.

so you can just declare it as:

@Root
class Address {
    @Attribute
    private final String street;

    @Attribute
    private final String city;

    @Attribute
    private final String state;

    public Address(String street, String city, String state) {
        super();
        this.street = street;
        this.city = city;
       this.state = state;
   }

   @Override
   public String toString() {
      return "Address [city=" + city + ", state=" + state + ", street=" + street + "]";
   }   
}
DJ
No, that does not work, at least in Simple 2.1.3.
binil
My bad, I didn't pay closer attention that you would like to have an immutable Address.Based on current simple, you'll need to have duplication of @Attribute tag, since it used the annotation on attribute for serializing and the constructor for deserializing. You can get away without name tag on attribute but not on constructor params, since the compiler only keep track of it by the order instead of by name.
DJ
Depend on what goal are you trying to achieve. Of course you can make the class mutable, and enforce the immutability manually in the setter. But then again, the code will get ugly. Between the two, I might just go with double annotations option.
DJ
@DJ Thanks for the clarification! I was expecting that the constructor argument annotation would need the name attribute (because the compiler drops the argument name), but removing the name attribute from the field leads to a 'Annotations do not match' error.
binil
A: 

Java will serialize all of your class members by default if they implement Serializable and adhere to the JavaBean syntax.

spork
I think you misunderstood the question. I want an XML->Java deserializer.
binil
Java serialization works both ways. If you serialize your Java objects to XML using Java serialization, you can also deserialize them from XML to Java objects. The process is transparent and flexible. In one application I use Java's XML serialization/deserialization to write object trees to disk and read them back at the user's request - we're talking hundreds of thousands of files - and it works well, in my opinion. Check out http://java.sys-con.com/node/37550 for examples - the key classes are `XMLEncoder` and `XMLDecoder`.
spork