Cod*_*lue 7 java jaxb marshalling
考虑以下抽象类 -
public abstract class Car
{
public abstract void drive(double miles);
}
Run Code Online (Sandbox Code Playgroud)
这是扩展上述类的示例类(用于说明目的).
public class Ferrari extends Car
{
private String lastUsed; // Ferrari specific field not in Car
private boolean f1Car; // Ferrari specific field not in Car
@XmlElement
public void setF1Car(boolean f1Car)
{
this.f1Car = f1Car;
}
public boolean isF1Car() { return f1Car; }
@XmlElement
public void setLastUsed(String lastUsed)
{
this.lastUsed = lastUsed;
}
public String getLastUsed() { return lastUsed; }
public void drive(double miles)
{
// implementation
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个包含Car对象的报表类 -
@XmlRootElement
public class CarTestReport
{
private String date;
private double miles;
private Car car;
@XmlElement
public void setDate(String date) { this.date = date;}
public String getDate() {return date;}
@XmlElement
public void setMiles(double miles) { this.miles = miles; }
public double getMiles() {return miles;}
@XmlElement
public void setCar(Car car) { this.car = car; }
public Car getCar() { return car; }
}
Run Code Online (Sandbox Code Playgroud)
以下是使用JAXB对MarsTestReport对象进行Marshall的代码 -
public static void main(String[] args) throws Exception
{
Ferrari ferrari = new Ferrari();
ferrari.setLastUsed("July 5 2012");
ferrari.setF1Car(false);
CarTestReport report = new CarTestReport();
report.setDate("July 6 2012");
report.setMiles(200);
report.setCar(ferrari);
File file = new File("carTestReport.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(CarTestReport.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(report, file);
}
Run Code Online (Sandbox Code Playgroud)
问题是,由于Car的抽象类型,JAXB忽略它并且在它对CarTestReport对象进行编组时不会对法拉利对象进行编组.我得到的输出是这个 -
<carTestReport>
<car/>
<date>July 6 2012</date>
<miles>200.0</miles>
</carTestReport>
Run Code Online (Sandbox Code Playgroud)
如您所见,即使已填充法拉利对象,也未在"汽车"节点下输入任何内容.如何解决这个问题呢?
csd*_*csd 17
对于任何可能的JAXB注释类,JAXB系统都不会查看类路径.你必须帮助它找到它们.在您的示例代码中,它根本不知道Ferrari
类的存在.(它只能看到Car
因为这是getter的返回类型CarTestReport
.)
告诉JAXB一个快速而又脏的方法Ferrari
是@XmlSeeAlso({Ferrari.class})
在Car
课堂顶部添加.然后你会得到这样的输出:
<carTestReport>
<car xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ferrari">
<f1Car>false</f1Car>
<lastUsed>July 5 2012</lastUsed>
</car>
<date>July 6 2012</date>
<miles>200.0</miles>
</carTestReport>
Run Code Online (Sandbox Code Playgroud)
告诉JAXB的另一种方法Ferrari
是将该类传递给JAXBContext.newInstance
方法,即:
JAXBContext jaxbContext = JAXBContext.newInstance(CarTestReport.class,
Ferrari.class);
Run Code Online (Sandbox Code Playgroud)
或者,如果所有JAXB类都在同一个包中,例如com.mycompany.carstuff
,那么你可以这样做:
JAXBContext jaxbContext = JAXBContext.newInstance("com.mycompany.carstuff");
Run Code Online (Sandbox Code Playgroud)
在最后一种情况下,它将搜索该包中的所有类.
如果你想让它发出一个名为的元素ferrari
(而不是<car xsi:type="ferrari">
上面的代码),一种可能性是添加@XmlType
到你的Car
类的顶部,如下所示:
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
@XmlSeeAlso({Ferrari.class})
@XmlType
public abstract class Car {
public abstract void drive(double miles);
}
Run Code Online (Sandbox Code Playgroud)
...并把@XmlRootElement
上Ferrari
,例如:
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Ferrari extends Car {
// ...
}
Run Code Online (Sandbox Code Playgroud)
根据我的理解,这种注释组合告诉JAXB Car
该类映射到XML模式类型(因此您不会获得任何名为"car"的元素),并且Ferrari
该类是该类型的元素(因此您可以拥有名为"法拉利"的元素.并且"根"在@XmlRootElement
误导......它可以是对象结构中的任何元素.
归档时间: |
|
查看次数: |
9373 次 |
最近记录: |