文章21 | 阅读 8247 | 点赞0
摘要: JAXB 作为JDK的一部分,能便捷地将Java对象与XML进行相互转换,本教程从实际案例出发来讲解JAXB 2 的那些事儿。完整版目录
上一节的Java对象都是相对基础的数据类型,这一节的数据多为复杂的类型。
Order对象中包含Product对象,这在项目中是常见情形。
public void test1() throws JAXBException { Product p = new Product(); p.setId("1100"); p.setName("Apple"); Order order = new Order(); order.setId("1101"); order.setPrice(23.45); order.setProduct(p); JAXBContext context = JAXBContext.newInstance(Order.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(order, System.out); }
Order对象的第三个属性是个复杂的数据类型。
@XmlRootElement(name = "Order") public class Order { private String id; private Double price; private Product product; //setters, getters }
被嵌套的 Product 不需要使用 @XmlRootElement
注解,使用注解 @XmlAccessorType
是因为我喜欢将注解标注在字段Filed
上面。
@XmlAccessorType(XmlAccessType.FIELD) public class Product { @XmlAttribute private String id; private String name; //setters, getters }
生成的XML含有两个层级。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order>
<id>1101</id>
<price>23.45</price>
<product id="1100">
<name>Apple</name>
</product>
</Order>
一般来说,一个Order不止含有一个Product,这时就需要使用到 List 了。
@Test public void test2() throws JAXBException { Product p1 = new Product(); p1.setId("11021"); p1.setName("Apple"); Product p2 = new Product(); p2.setId("11022"); p2.setName("Banana"); List<Product> list = Arrays.asList(p1,p2); Order2 order = new Order2(); order.setId("1102"); order.setPrice(45.67); order.setProduct(list); JAXBContext context = JAXBContext.newInstance(Order2.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(order, System.out); }
对象 Order 的第三个字段是 List 类型。Product和上例中的一样。
@XmlRootElement(name = "Order") public class Order2 { private String id; private Double price; private List<Product> product; //setters, getters }
生成的XML中 product 重复出现多次。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order>
<id>1102</id>
<price>45.67</price>
<product id="11021">
<name>Apple</name>
</product>
<product id="11022">
<name>Banana</name>
</product>
</Order>
上例中的Product是散落着的数据,有时候可能需要将其包裹起来,这时只需要改动 Order 对象,添加@XmlElementWrapper
。
@XmlRootElement(name = "Order") @XmlAccessorType(XmlAccessType.FIELD) public class Order3 { private String id; private Double price; @XmlElementWrapper(name = "Products") private List<Product> product;
编组过程和上例中的相同,生成的XML包含了一个 Products 包裹着所有的 Product
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order>
<id>1102</id>
<price>45.67</price>
<Products>
<product id="11021">
<name>Apple</name>
</product>
<product id="11022">
<name>Banana</name>
</product>
</Products>
</Order>
有一点需要注意,之前所有的字段都指定了数据,如果不指定数据,就能生成不一样的XML。
@Test public void test4() throws JAXBException { Product p1 = new Product(); p1.setId("11041"); Product p2 = new Product(); p2.setId("11042"); p2.setName("Grape"); List<Product> list = Arrays.asList(p1,p2); Order3 order = new Order3(); order.setId("1104"); order.setProduct(list); JAXBContext context = JAXBContext.newInstance(Order3.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(order, System.out); }
生成的XML只包含上面指定数据的字段。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order>
<id>1104</id>
<Products>
<product id="11041"/>
<product id="11042">
<name>Grape</name>
</product>
</Products>
</Order>
有时候,Products元素下面并不只是加入 product ,可能动态加入各种商品。
这次的模拟的商品是糕点与饼干。
这里的 Cake 只包含一个字段,需要注意的是 @XmlRootElement
不能少。
@XmlRootElement(name = "Cake") public class Cake { private String name; //setters, getters }
这里的 Biscuit 也只包含一个字段。
@XmlRootElement(name = "Biscuit") public class Biscuit { private String name; //setters, getters }
Order的第三个字段是List,但是没有指定一个特定对象,用了Object代指所有,还有一个@XmlAnyElement
是重要的注解,用来标注所有的Element。
@XmlRootElement(name = "Order") @XmlAccessorType(XmlAccessType.FIELD) public class Order4 { private String id; private Double price; @XmlElementWrapper(name = "Products") @XmlAnyElement private List<Object> product; //setters, getters }
下面用来模拟数据生成,注意的是JAXBContext需要注册所有需要编组的Java bean。这一点和之前的例子是不同的。
@Test public void test4() throws JAXBException { Cake cake = new Cake(); cake.setName("Nobel"); Biscuit biscuit = new Biscuit(); biscuit.setName("PB"); List<Object> list = Arrays.asList(cake,biscuit); Order4 order = new Order4(); order.setId("1104"); order.setProduct(list); JAXBContext context = JAXBContext.newInstance(Order4.class, Cake.class, Biscuit.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(order, System.out); }
生成的XML包含了一个 Products ,其数据结构在Order中并没有指定,方便后期扩展。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order>
<id>1104</id>
<Products>
<Cake>
<name>Nobel</name>
</Cake>
<Biscuit>
<name>PB</name>
</Biscuit>
</Products>
</Order>
与动态Element对应的是Attribute,不过需要注意的是,动态 Attribute 需要的是 Map ,而且其 key 的类型需要指定为 QName
,这个QName
在复杂的 XML 生成时有很大用处。一般使用到的是其QName(name)
,它还有一个形式为QName(name,namespace)
,可以指定命名空间,在某些场景下有不可替代的作用。
@XmlRootElement(name = "Order") @XmlAccessorType(XmlAccessType.FIELD) public class Order5 { @XmlAnyAttribute private Map<QName, String> properties; private Product product; //setters, getters }
Product与之前的一样,Map的key是特殊类型。
@Test public void test5() throws JAXBException { Product p = new Product(); p.setId("1105"); p.setName("Apple"); Map<QName, String> map = new HashMap<>(); map.put(new QName("id"), "1105"); map.put(new QName("classification"), "food"); map.put(new QName("type"), "fruit"); Order5 order = new Order5(); order.setProduct(p); order.setProperties(map); JAXBContext context = JAXBContext.newInstance(Order5.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(order, System.out); }
仅关注 Order 的 Attribute , 可以发现我们在 Order 中没有指定任何与之相关的字段,只是在HashMap
中加了几组数据,现在编组成为了Attribute。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order id="1105" classification="food" type="fruit">
<product id="1100">
<name>Apple</name>
</product>
</Order>
可以在GitHub找到完整代码。
本节代码均在该包下:package com.example.demo.lesson11;
本节介绍了 JAXB 编组为复杂 XML 的场景,下一节还将继续扩展一些实用的场景。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://jiangchao.blog.csdn.net/article/details/82818240
内容来源于网络,如有侵权,请联系作者删除!