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

时间:2013-03-14 20:08:46

标签: java derived-class simple-framework

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

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

    <example1>
       <things>
          <fruit class="com.mumpitz.simplexmltest.Apple" id="17">
             <sugar>212</sugar>
          </fruit>
          <fruit class="com.mumpitz.simplexmltest.Orange" id="25" weight="11.2"/>
       </things>
    </example1>

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

    <example1>
       <things>
          <apple id="17">
             <sugar>212</sugar>
          </apple>
          <orange id="25" weight="11.2"/>
       </things>
    </example1>

'apple'和'orange'元素没有class属性,而不是'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<Fruit> things = new ArrayList<Fruit>();

        @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 个答案:

答案 0 :(得分:4)

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

  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<Thing> list = new ArrayList<Thing>();
    
        public void add(Thing t) {
            list.add(t);
        }
    
        public List<Thing> 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;
        }
    }