Easy XML Serializer for Java
I'm looking for a way to serialize Java objects into XML for use by a RESTful web service. I don't have an XSD.
I have looked at the following:
开发者_运维问答JAXB - fairly heavy weight with annotations required on classes and also an ObjectFactory class and/or a jaxb.index file
Simple - requires annotations but no other config classes/files. Unfortunately it can't serialize Sets.
XStream - no annotations etc. required, but doesn't support generics
Does anyone else have any suggestions?
import java.beans.XMLEncoder;
import java.beans.XMLDecoder;
import java.io.*;
public class XMLSerializer {
public static void write(Object f, String filename) throws Exception{
XMLEncoder encoder =
new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream(filename)));
encoder.writeObject(f);
encoder.close();
}
public static Object read(String filename) throws Exception {
XMLDecoder decoder =
new XMLDecoder(new BufferedInputStream(
new FileInputStream(filename)));
Object o = (Object)decoder.readObject();
decoder.close();
return o;
}
}
JAXB is pretty painless, and comes with Java 6, and it has a low footprint.
You get this for the price of one annotation.
Order.java
package xxx;
import java.util.Date;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Order {
int custId;
Date orderDate;
String description;
List<Item> items;
public void setCustId(int custId) {
this.custId = custId;
}
public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}
public void setDescription(String description) {
this.description = description;
}
public void setItems(List<Item> items) {
this.items = items;
}
public int getCustId() {
return custId;
}
public Date getOrderDate() {
return orderDate;
}
public String getDescription() {
return description;
}
public List<Item> getItems() {
return items;
}
public String toString() {
return "Order: " + custId + " - " + orderDate + " - " + description + " - " + items;
}
}
Item.java:
package xxx;
public class Item {
String name;
private int qty;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
public String toString() {
return "Item:" + name + " - " + qty;
}
}
Test.java:
package xxx;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Test {
public static void main(String args[]) throws Exception {
Order o = new Order();
o.setCustId(123);
o.setDescription("New order");
o.setOrderDate(new Date());
List<Item> items = new ArrayList<Item>();
Item i = new Item();
i.setName("Duck Soup");
i.setQty(10);
items.add(i);
i = new Item();
i.setName("Carrots");
i.setQty(4);
items.add(i);
o.setItems(items);
//Write it
JAXBContext ctx = JAXBContext.newInstance(Order.class);
Marshaller m = ctx.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter sw = new StringWriter();
m.marshal(o, sw);
sw.close();
System.out.println(sw.toString());
// Read it back
JAXBContext readCtx = JAXBContext.newInstance(Order.class);
Unmarshaller um = readCtx.createUnmarshaller();
Order newOrder = (Order) um.unmarshal(new StringReader(sw.toString()));
System.out.println(newOrder);
}
}
Results:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<order>
<custId>123</custId>
<description>New order</description>
<items>
<name>Duck Soup</name>
<qty>10</qty>
</items>
<items>
<name>Carrots</name>
<qty>4</qty>
</items>
<orderDate>2010-06-16T18:12:06.870-07:00</orderDate>
</order>
Order: 123 - Wed Jun 16 18:12:06 PDT 2010 - New order - [Item:Duck Soup - 10, Item:Carrots - 4]
My vote would be for XStream. The lack of generics support is a small price to pay for the amount of flexibility it offers. You can also easily implement generics by serializing the generic class type at serialization time, or build this into your domain objects. E.g.
class Customer
{
List<Order> orders;
public List<Order> getOrders()
{
return orders;
}
}
In the stream, the element type denotes the type of each object. When the type is an abstract type or interface, the element listed with the implementing class, unless that has been specified as the default for that interface type. (E.g. ArrayList as the default for instances of static type List.)
Generics are "rose coloured glasses" in java - they don't really change what you are seeing, just how you see it. The objects would be sent over the wire exactly the same if they were sent with generics support or not.
You can try JLibs XMLDocument. It uses SAX to create XML and thus light-weight and have complete control.
精彩评论