2013-03-14 61 views
2

我想序列化一個對象層次結構,包括從基類「Thing」派生的對象列表。這工作得很好,包括反序列化 - 但以書面指定實際使用的Java類Simple-XML - 如何序列化集合中的派生類?

當我創建與下面的Java代碼的XML文件中的屬性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> 

「蘋果」和不帶類屬性「橙色」的元素,而不是「果」以這樣的屬性。這可能嗎?

(第二個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; 
     } 
    } 

回答

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