“小伙子,还不快!我还有两节课要教给你!”

“两个?哇。好吧,好吧。你不会做什么来增强自己的冷静!我洗耳恭听。”

“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 上下文,因为它们都参与序列化。”

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

“是的,我为你感到高兴。现在,稍微休息一下,我们继续。”