“小伙子,还不快!我还有两节课要教给你!”
“两个?哇。好吧,好吧。你不会做什么来增强自己的冷静!我洗耳恭听。”
“XML 和 JSON 一样,经常在不同程序和计算机之间传递数据时使用。并且有几种框架可以大大简化 Java 程序员在使用 XML 时的生活。今天我将向您介绍其中的一种。”
“JAXB 是用于处理 XML 的优秀多用途框架。”

“JAXB 是 JDK 的一部分,因此您不需要单独下载它。”
“我先给大家举个例子,具体怎么用,然后我们再分析,比如:”
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);
}
@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 反序列化的示例:”
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);
}
@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 方法而不是字段。”
“这是我承诺的例子:”
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());
}
@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 行。这里我们将两个类(Zoo和Cat)传递给 JAXB 上下文,因为它们都参与序列化。”
“今天是非常有趣的一天。有很多新信息。”
“是的,我为你感到高兴。现在,稍微休息一下,我们继续。”
GO TO FULL VERSION