“小伙子,還不快!我還有兩節課要教給你!”

“兩個?哇。好吧,好吧。你不會做什麼來增強自己的冷靜!我洗耳恭聽。”

“XML 和 JSON 一樣,經常在不同程序和計算機之間傳遞數據時使用。並且有幾種框架可以大大簡化 Java 程序員在使用 XML 時的生活。今天我將向您介紹其中的一種。”

“JAXB 是用於處理 XML 的優秀多用途框架。”

日本航空航天局 - 1

“JAXB 是 JDK 的一部分,因此您無需單獨下載。”

“我先給大家舉個例子,具體怎麼用,然後我們再分析,比如:”

將對象轉換為 XML
public static void main(String[] args) throws JAXBException
{
 // Create an object to be serialized into XML
 Cat cat = new Cat();
 cat.name = "Missy";
 cat.age = 5;
 cat.weight = 4;

 // Write the result of the serialization to a StringWriter
 StringWriter writer = new StringWriter();

 // Create a Marshaller object that will perform the serialization
 JAXBContext context = JAXBContext.newInstance(Cat.class);
 Marshaller marshaller = context.createMarshaller();
 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
 // And here's the serialization itself:
 marshaller.marshal(cat, writer);

 // Convert everything written to the StringWriter
 String result = writer.toString();
 System.out.println(result);
}
對象轉換為 XML 的類
@XmlType(name = "cat")
@XmlRootElement
public class Cat
{
 public String name;
 public int age;
 public int weight;

 public Cat()
 {
 }
}
序列化結果和屏幕輸出:
<cat> 
<name> Missy </name> 
<age> 5 </age> 
<weight> 4 </weight> 
</cat>

“出於某種原因,一行一行地,這段代碼讓我想起了 JSON 序列化。相同的註釋,但 JSON 使用了 ObjectMapper,而這使用了 Context 和 Marshaller。”

“是的。他們真的很相似。傑克遜是以 JAXB 為藍本的。但 JAXB 也是從某個地方復制的。你不能從頭開始發明天才。”

“好像是這樣。”

“好的,這就是發生的事情:”

“在第 4-7 行中,我們創建了一個Cat對象並用數據填充它。”

“在第 10 行,我們創建了一個 Writer 對象來寫入結果。”

“在第 13 行,我們創建了‘context’。這類似於 ObjectMapper,但隨後從中創建了兩個額外的子對象。Marshaller用於序列化,而Unmarshaller用於反序列化。與 Jackson 有細微差別,但它不是根本不同。”

“在第 14 行,我們創建了一個Marshaller對象。Marshalling 是序列化的同義詞。”

“在第 15 行,我們將 FORMATTED_OUTPUT 屬性設置為 TRUE。這將在結果中添加換行符和空格,以便代碼易於閱讀,而不是將所有文本都放在一行中。”

“在第 17 行,我們序列化對象。”

“在第 20-21 行,我們在屏幕上顯示序列化的結果。”

“什麼是 @XmlType(name = 'cat&') 和 @XmlRootElement 註釋?”

" @XmlRootElement表示這個對象可以是 XML 元素的'樹根'。換句話說,它可以是最高級別的元素,並且可以包含所有其他元素。"

" @XmlType(name = 'cat')表示該類參與了 JAXB 序列化,同時也為該類指定了 XML 標籤的名稱。"

“好吧,現在我將向您展示一個 XML 反序列化的示例:”

從 XML 轉換對象
public static void main(String[] args) throws JAXBException
{
 String xmldata = "<cat><name>Missy</name><age>5</age><weight>4</weight></cat>";
 StringReader reader = new StringReader(xmldata);

 JAXBContext context = JAXBContext.newInstance(Cat.class);
 Unmarshaller unmarshaller = context.createUnmarshaller();

 Cat cat = (Cat) unmarshaller.unmarshal(reader);
}
其對像從 XML 反序列化的類
@XmlType(name = "cat")
@XmlRootElement
public class Cat
{
 public String name;
 public int age;
 public int weight;

 public Cat()
 {
 }
}

“一切都和傑克遜幾乎一樣。但為了以防萬一,我會解釋這裡發生的一切。”

“在第 3 行,我們傳遞了一個存儲要反序列化的 XML 的字符串。”

“在第 4 行,我們將 XML 字符串包裝在StringReader中。”

“在第 6 行中,我們創建了一個JAXB 上下文,我們將類列表傳遞給它。”

“在第 7 行,我們創建了一個Unmarshaller——將執行反序列化的對象。”

“在第 9 行中,我們從 reader 對象反序列化 XML 並獲得一個 Cat 對象。”

“現在一切似乎都很明顯。但幾個小時前,我還在絞盡腦汁想弄清楚它是如何工作的。”

“當你變得更聰明時,這總會發生。複雜的事情變得簡單。”

“我變聰明了?我不禁為此感到高興。”

“太好了。下面是一個註釋列表,您可以使用它來控制 JAXB 序列化的結果:”

JAXB 註釋 描述
@XmlElement(名稱) 放置在田野附近。
該字段將存儲在 XML 元素中。
讓您設置標籤的名稱。
@XmlAttribute(名稱) 放置在田野附近。
該字段將存儲為 XML 屬性!
讓您設置屬性的名稱。
@XmlElementWrapper(nillable = true) 放置在田野附近。
允許您為一組元素設置“包裝標籤”。
@Xml類型 放在班級附近。
如果默認構造函數是私有的,則允許您指定用於創建對象的方法。
@XmlJavaTypeAdapter 放置在田野附近。
允許您指定將字段轉換為字符串的類。

“多麼有趣!但是你能給我提供一個使用這些註釋的例子嗎?解釋是一回事,但一個有效的例子是另一回事。”

“好的。我會給你看一個例子。我只是想補充一點,JAXB 允許你註釋 getter/setter 方法而不是字段。”

“這是我承諾的例子:”

將對象轉換為 XML
public static void main(String[] args) throws JAXBException
{
 // Create Cat and Zoo objects to be serialized into XML
 Cat cat = new Cat();
 cat.name = "Missy";
 cat.age = 5;
 cat.weight = 4;

 Zoo zoo = new Zoo();
 zoo.animals.add(cat);
 zoo.animals.add(cat);

 // Write the result of the serialization to a StringWriter
 StringWriter writer = new StringWriter();

 // Create a Marshaller object that will perform the serialization
 JAXBContext context = JAXBContext.newInstance(Cat.class, Zoo.class);
 Marshaller marshaller = context.createMarshaller();
 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
 // Here's the serialization itself
 marshaller.marshal(zoo, writer);

 // Convert everything written to the StringWriter into a String
 System.out.println(writer.toString());
}
對象轉換為 XML 的類
@XmlType(name = "zoo")
@XmlRootElement
public class Zoo
{
 @XmlElementWrapper(name = "wild-animals", nillable = true)
 @XmlElement(name = "tiger")
 public List<Cat> animals = new ArrayList<>();
}

public class Cat
{
 @XmlElement(name = "catname")
 public String name;
 @XmlAttribute(name = "age")
 public int age;
 @XmlAttribute(name = "w")
 public int weight;

 public Cat()
 {
 }
}
序列化結果和屏幕輸出:
<
動物園> <野生動物
> <tiger age = "5" w = "4"> 
<catname>Missy</catname> 
</tiger> 
<tiger age = "5" w = "4"> 
<catname>Missy </貓名> < 
/老虎> < 
/野生動物> 
</動物園>

“請注意,這次我們沒有序列化 Cat 對象,而是一個存儲 Cat 對象集合的 Zoo 對象。”

“cat 對像被添加到集合中兩次,所以它在 XML 中出現了兩次。”

“該系列有自己的‘野生動物’標籤,包裹了該系列的所有元素。”

age & weight元素已經變成了age &w w 屬性。”

“使用@XmlElement屬性,我們將cat 標籤更改為 tiger 標籤。”

“注意第 17 行。這裡我們將兩個類(ZooCat)傳遞給 JAXB 上下文,因為它們都參與序列化。”

“今天是非常有趣的一天。有很多新信息。”

“是的,我為你感到高興。現在,稍微休息一下,我們繼續。”