Simple-XML – 如何序列化集合中的派生类?

我想序列化一个对象层次结构,包括一个派生自基类“Thing”的对象列表。 这很好用,包括反序列化 – 但XML-Simple坚持编写一个指定实际使用的Java类的属性

当我使用下面的java代码创建一个xml文件时,内容如下:

   212     

但这不是我想要的。 我想要

     212     

没有class属性的’apple’和’orange’元素,不具有这种属性的’fruit’。 这可能吗?

(第二个xml符合现有架构;添加额外属性不是一个选项)

这是代码:

  package com.mumpitz.simplexmltest; import java.io.File; import java.util.ArrayList; import org.simpleframework.xml.Attribute; import org.simpleframework.xml.Element; import org.simpleframework.xml.ElementList; import org.simpleframework.xml.Root; import org.simpleframework.xml.Serializer; import org.simpleframework.xml.core.Persister; class Fruit { @Attribute(name = "id") protected final int id; Fruit( @Attribute(name = "id") int id) { this.id = id; } int getObjectId() { return id; } } @Root class Apple extends Fruit { private final int sugar; @Element(type = Fruit.class) public Apple( @Attribute(name = "id") int id, @Element(name = "sugar") int sugar) { super(id); this.sugar = sugar; } @Element(name = "sugar") public int getSugar() { return this.sugar; } @Override public String toString() { return "id: " + id + ", sugar: " + sugar; } } @Root class Orange extends Fruit { @Attribute public double weight; public Orange( @Attribute(name = "id") int id) { super(id); } @Override public String toString() { return "id: " + id + ", weight: " + weight; } } @Root public class Example1 { @ElementList public ArrayList things = new ArrayList(); @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("things:\n"); for (int i=0; i<things.size(); i++) { sb.append(" " + things.get(i).toString() + "\n"); } return sb.toString(); } ////////////////////////////////// static Example1 createDummy() { Example1 d = new Example1(); d.things.add(new Apple(17, 212)); Orange or = new Orange(25); or.weight = 11.2; d.things.add(or); return d; } static String msg; static Example1 res; static public String getMessage() { String m = msg; msg = null; return m; } static public boolean write(String path) { Serializer serializer = new Persister(); Example1 example = Example1.createDummy(); File result = new File(path); try { serializer.write(example, result); } catch (Exception e) { e.printStackTrace(); msg = e.getMessage(); return false; } return true; } static public boolean read(String path) { Serializer serializer = new Persister(); File source = new File(path); try { res = serializer.read(Example1.class, source); } catch (Exception e) { e.printStackTrace(); msg = e.getMessage(); return false; } return true; } public static Object getResult() { return res; } } 

几个小时后,我找到了解决方案。 你只需要

  1. 阅读手册
  2. 使用@ElementListUnion批注

     package com.mumpitz.simplexmltest; import java.io.File; import java.util.ArrayList; import java.util.List; import org.simpleframework.xml.Attribute; import org.simpleframework.xml.Element; import org.simpleframework.xml.ElementList; import org.simpleframework.xml.ElementListUnion; import org.simpleframework.xml.Root; import org.simpleframework.xml.Serializer; import org.simpleframework.xml.core.Persister; // the base class @Element class Thing { static int count=0; Thing() { this.id = ++count; } @Attribute protected int id; public int getId() { return id; } } // first derived class @Element class Car extends Thing { @Attribute private String name; Car(@Attribute(name="name") String name) { this.name = name; } public String getName() { return name; } @Override public String toString() { return "ID: " + id + " Car: " + name; } } // second derived class @Element class House extends Thing { @Attribute private int price; House(@Attribute(name="price") int price) { this.price = price; } public int getPrice() { return this.price; } @Override public String toString() { return "ID: " + id + " House: " + price; } } // a class with a list of base class instances @Root(name="ListOfThings") public class Example4 { // specify the derived classes used in the list @ElementListUnion({ @ElementList(entry="house", inline=true, type=House.class), @ElementList(entry="car", inline=true, type=Car.class) }) private ArrayList list = new ArrayList(); public void add(Thing t) { list.add(t); } public List getProperties() { return list; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Example4 contains " + list.size() + " elements:\n"); for (Thing t : list) { sb.append(" " + t.toString() + "\n"); } return sb.toString(); } ////////////////////////////////// // test code ////////////////////////////////// static String msg; static Example4 res; static public String getMessage() { String m = msg; msg = null; return m; } static private Example4 createDummy() { Example4 d = new Example4(); d.add(new Car("Mercedes")); d.add(new House(34000000)); d.add(new Car("VW")); d.add(new House(230000)); return d; } ////////////////////////////////// // serialize / deserialize ////////////////////////////////// static public boolean write(String path) { Serializer serializer = new Persister(); File result = new File(path); Example4 example = Example4.createDummy(); try { serializer.write(example, result); } catch (Exception e) { e.printStackTrace(); msg = e.getMessage(); return false; } return true; } static public boolean read(String path) { Serializer serializer = new Persister(); File source = new File(path); try { res = serializer.read(Example4.class, source); } catch (Exception e) { e.printStackTrace(); msg = e.getMessage(); return false; } return true; } public static Object getResult() { return res; } }