使用JAXB编组/解组Java超类和子类

我一直在试验JAXB教程,并设法让代码工作,从Java对象生成XML文件,然后能够使用XML生成Java对象。 目前,它会读取同一个类的多个实例,以创建类似于下面的XML文件

 TR54 red 5   BN04 THY yellow 3   BN05 THY yellow 5  

我希望能够使用JAXB技术来处理子类。 例如:假设我有一个Car,Van和Bicycle对象是Vehicle的子类。 我是否可以操作我的JAXB类来编写一个XML文件来生成与此类似的东西? 我已经提供了我正在使用的代码。

   TR54 red 5   MN05 RFD red 5   ZX54 UJK red 1   

主类

 package basictransport2; public class Main { public static void main(String[] args) { JAXB parser = new JAXB(); parser.marshall(); //parser.unmarshallList(); } } 

车辆类

 package basictransport2; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; //@XmlRootElement(name = "Vehicle") public class Vehicle { private int ownerId; public Vehicle(int ownerId) { this.setOwnerId(ownerId); } //@XmlElement (name = "Owner ID") public int getOwnerId() { return ownerId; } public void setOwnerId(int ownerId) { this.ownerId = ownerId; } public int getEnergyRating() { return (Integer) null; } public String getColour() { return null; } public String getRegPlate() { return null; } } 

汽车类

 package basictransport2; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; //@XmlRootElement(name = "Car") public class Car extends Vehicle { private String regPlate; private int energyRating; private String colour; public Car(String regPlate, int energyRating, String colour, int ownerId) { super(ownerId); this.regPlate = regPlate; this.energyRating = energyRating; this.colour = colour; } public Car(int ownerId) { super(ownerId); } //@XmlElement (name = "Registration") public String getRegPlate() { return regPlate; } public void setRegPlate(String regPlate) { if(this.regPlate == null) { this.regPlate = regPlate; } } //@XmlElement (name = "Energy Rating") public int getEnergyRating() { return energyRating; } public void setEnergyRating(int energyRating) { this.energyRating = energyRating; } //@XmlElement (name = "Colour") public String getColour() { return colour; } public void setColour(String colour) { this.colour = colour; } } 

JAXB类

 package basictransport2; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; public class JAXB { public void marshall() { try { List vehicleList = new ArrayList(); vehicleList.add(new Car("SG09 TYH", 4, "Yellow", 1)); vehicleList.add(new Car("XX09 VVV", 3, "Red", 2)); vehicleList.add(new Car("BL09 TYZ", 4, "Blue", 3)); Garage listOfVehicles = new Garage(); listOfVehicles.setListOfVehicles(vehicleList); JAXBContext context = JAXBContext.newInstance(Garage.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(listOfVehicles, System.out); marshaller.marshal(listOfVehicles, new File("src\\data\\listcar.xml")); } catch(Exception e) { System.out.println(e.getMessage()); } } public void unmarshall() { try { JAXBContext context = JAXBContext.newInstance(Garage.class); Unmarshaller unmarhsaller = context.createUnmarshaller(); Garage listOfVehicles = (Garage)unmarhsaller.unmarshal(new File("src\\data\\listcar.xml")); System.out.println("List Car information"); for(Vehicle vehicle : listOfVehicles.getListOfVehicles()) { System.out.println("Reg Plate: " + vehicle.getRegPlate()); System.out.println("Energy Rating: " + vehicle.getEnergyRating()); System.out.println("Colour: " + vehicle.getColour()); System.out.println("================"); } } catch (Exception e) { System.out.println(e.getMessage()); } } } 

列表类

 package basictransport2; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlType; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name="Vehicle") public class Garage { @XmlElements ({ @XmlElement(name = "Car", type = Car.class, required = false) }) private List vehicleCollection = new ArrayList(); public List getListOfVehicles() { return vehicleCollection; } public void setListOfVehicles(List listOfVehicles) { this.vehicleCollection = listOfVehicles; } } 

谢谢各位的意见。 我使用了你所有答案的反馈,但最终它们的组合起了作用,这就是为什么我为将来可能遇到这个问题的人创建了一个单独的答案。

为了实现这一点,我必须确保使用@XmlElement对超级和子类中的所有getter方法进行marhsalled / unmarshalled注释。 这将确定相应变量的XML标记。

 @XmlElement (name = "OwnerID") public int getOwnerId() { return ownerId; } 

必须使用@XmlSeeAlso注释超类以将子类绑定到它。 即在我的代码中, RoadVehicle是超类, CarVan类都扩展了它。

 @XmlSeeAlso({Car.class, Van.class}) public class Vehicle { 

现在,超级和子类被注释,唯一需要注释的其他类是列表类(我的代码中的Garage)。 此处的更改将确定填充XML标记的内容。

通过将@XmlRootElement批注应用于类的顶部来设置根XML标记。 即“Vehicle”将是我的示例中的根XML标记。

 @XmlRootElement(name = "Vehicle") public class Garage { 

最后,必须使用@XmlElements注释声明@XmlElements列表,每个子类需要一个XML标记,其name提供XML标记的name 。 必须在集合的getter方法之上声明此列表。

 @XmlElements ({ @XmlElement(name = "Car", type = Car.class, required = false), @XmlElement(name = "Van", type = Van.class, required = false) }) public List getListOfVehicles() { return vehicleCollection; } 

你走在正确的轨道上。 下面的内容可能有所帮助

 @XmlRootElement(name = "car") public class Car extends BasicType{ } @XmlRootElement(name = "van") public class Van extends BasicType{ } @XmlRootElement(name = "vehicle") public class Vehicle { List basicType; } 

最简单的解决方案是为汽车和货车设置不同的子类,即使它们没有向基类添加任何内容。 然后,根元素类包含基类的列表,其中元素QNames标识实际的类。

 @XmlRootElement
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name =“Vehicle”)
公共类车辆{
     @XmlElements({
         @XmlElement(name =“Car”,type = Car.class,required = false),
         @XmlElement(name =“Van”,type = Van.class,required = false)
     })
     protected list carOrVan;
     public List getCarOrVan(){
         if(carOrVan == null){
             carOrVan = new ArrayList();
         }
        返回this.carOrVan;
     }
 }

这是基类和子类:

公共类Basic {
     private String regplate;
    私人字符串颜色;
    私人字符串能量;

     public String getRegplate(){return regplate;  }
     public void setRegplate(String v){regplate = v;  }
     public String getColor(){return color;  }
     public void setColor(String v){color = v;  }
     public String getEnergyrating(){return energyrating;  }
     public void setEnergyrating(String v){energyrating = v;  }
 }

公共类汽车扩展基本{}

公共类Van扩展Basic {}

如果汽车和货车发展成不同的子类,这将是顺利的。