[英]Java/JAXB: Unmarshall XML attributes to specific Java object attributes
[英]Java/JAXB: Unmarshall Xml to specific subclass based on an attribute
是否可以使用JAXB根據xml的屬性將xml解組為特定的Java類?
<shapes>
<shape type="square" points="4" square-specific-attribute="foo" />
<shape type="triangle" points="3" triangle-specific-attribute="bar" />
</shapes>
我想有一個包含三角形和正方形的Shape對象列表,每個對象都有自己的特定於形狀的屬性。 IE:
abstract class Shape {
int points;
//...etc
}
class Square extends Shape {
String square-specific-attribute;
//...etc
}
class Triangle extends Shape {
String triangle-specific-attribute;
//...etc
}
我目前只是將所有屬性放在一個大的“Shape”類中,並且它不太理想。
如果形狀被恰當地命名為xml元素,我可以讓它工作,但不幸的是我無法控制我正在檢索的xml。
謝謝!
JAXB是一個規范,具體實現將提供擴展點來做這樣的事情。 如果您使用的是EclipseLink JAXB(MOXy) ,則可以按如下方式修改Shape類:
import javax.xml.bind.annotation.XmlAttribute;
import org.eclipse.persistence.oxm.annotations.XmlCustomizer;
@XmlCustomizer(ShapeCustomizer.class)
public abstract class Shape {
int points;
@XmlAttribute
public int getPoints() {
return points;
}
public void setPoints(int points) {
this.points = points;
}
}
然后使用MOXy @XMLCustomizer,您可以訪問InheritancePolicy並將類指示符字段從“@xsi:type”更改為“type”:
import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
public class ShapeCustomizer implements DescriptorCustomizer {
@Override
public void customize(ClassDescriptor descriptor) throws Exception {
descriptor.getInheritancePolicy().setClassIndicatorFieldName("@type");
}
}
您將需要確保在模型類(Shape,Square等)中包含jaxb.properties文件,並使用以下條目指定EclipseLink MOXy JAXB實現:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
以下是其他模型類:
形狀
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Shapes {
private List<Shape> shape = new ArrayList<Shape>();;
public List<Shape> getShape() {
return shape;
}
public void setShape(List<Shape> shape) {
this.shape = shape;
}
}
廣場
import javax.xml.bind.annotation.XmlAttribute;
public class Square extends Shape {
private String squareSpecificAttribute;
@XmlAttribute(name="square-specific-attribute")
public String getSquareSpecificAttribute() {
return squareSpecificAttribute;
}
public void setSquareSpecificAttribute(String s) {
this.squareSpecificAttribute = s;
}
}
三角形
import javax.xml.bind.annotation.XmlAttribute;
public class Triangle extends Shape {
private String triangleSpecificAttribute;
@XmlAttribute(name="triangle-specific-attribute")
public String getTriangleSpecificAttribute() {
return triangleSpecificAttribute;
}
public void setTriangleSpecificAttribute(String t) {
this.triangleSpecificAttribute = t;
}
}
下面是一個演示程序,用於檢查一切是否正常:
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(Shapes.class, Triangle.class, Square.class);
StringReader xml = new StringReader("<shapes><shape square-specific-attribute='square stuff' type='square'><points>4</points></shape><shape triangle-specific-attribute='triangle stuff' type='triangle'><points>3</points></shape></shapes>");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Shapes root = (Shapes) unmarshaller.unmarshal(xml);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
我希望這有幫助。
有關EclipseLink MOXy的更多信息,請參閱:
編輯
在EclipseLink 2.2中,我們使這更容易配置,請查看以下文章以獲取更多信息:
注釋@XmlElements使您可以指定哪個標記與哪個子類相對應。
@XmlElements({
@XmlElement(name="square", type=Square.class),
@XmlElement(name="triangle", type=Triangle.class)
})
public List<Shape> getShape() {
return shape;
}
另請參閱@XmlElements的 javadoc
AFAIK,您必須編寫一個XmlAdapter ,它知道如何處理Shape的編組/解組。
不,我擔心這不是一個選擇,JAXB不是那么靈活。
我可以建議的最好的是你在Shape
類上放置一個方法,它根據屬性實例化“正確”類型。 客戶端代碼將調用該工廠方法來獲取它。
我能想出最好的,對不起。
有@XmlSeeAlso注釋來告訴綁定子類。
例如,使用以下類定義:
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
用戶需要創建JAXBContext作為JAXBContext.newInstance(Dog.class,Cat.class)(動物將自動拾取,因為Dog和Cat引用它。)
XmlSeeAlso注釋將允許您編寫:
@XmlSeeAlso({Dog.class,Cat.class})
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.