【问题标题】:Simple-XML - how to serialize derived classes in a collection?Simple-XML - 如何序列化集合中的派生类?
【发布时间】:2013-03-03 09:19:24
【问题描述】:

我想序列化一个对象层次结构,包括从基类“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;
        }
    }

【问题讨论】:

    标签: java derived-class simple-framework


    【解决方案1】:

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

    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;
          }
      }
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多