JAXB(Java Architecture for XML Binding)
一、code
1.java bean->xml
@Test
public void marshalTest() {
try {
JAXBContext jContext = JAXBContext.newInstance(User.class);
Marshaller marshaller = jContext.createMarshaller();
Pet pet = new Pet("dog","小哈");
Book aBook = new Book("平凡的世界", 20);
Book bBook = new Book("明晓溪",15);
List<Book> books = new ArrayList<Book>();
books.add(aBook);
books.add(bBook);
User user = new User("张三","女", 20, new Date(), null, pet, books);
//设置生成的xml的编码
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
//设置生成的xml内容是否format,否的话是显示一行
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//是否省略头部声明信息,默认false
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
//直接输出文件
marshaller.marshal(user, new File("a.xml"));
OutputStream out = new ByteArrayOutputStream();
//输出字节流
marshaller.marshal(user, out);
System.out.println("========"+out.toString());
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
JDK1.7及之后做了更多封装,更加简单:
JAXB.marshal(user, new File("b.xml"));
2.xml->javabean
@Test
public void unmarshallTest() {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(User.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
User user = (User) unmarshaller.unmarshal(new File("a.xml"));
System.out.println(user.toString());
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1.7及之后:
User user2 = JAXB.unmarshal(new File("b.xml"), User.class);
二、重要注解
1.@XmlRootElement(必要)
//根元素默认类名首字母小写。设置name后,map到name。设置namespace后,生成到的根元素-><ns2:person xmlns:ns2="com">
@XmlRootElement(name="person",namespace="com")
public class User{
2.@XmlElement
@XmlElement(name="name1")//此注解用于属性与xml元素到map。可加在属性上(private的会报错),或get/set方法上。
@XmlElement(name=""namespace="com1")//设置后,根元素-><ns3:person xmlns:ns2="com1" xmlns:ns3="com">,对应元素-><ns2:sex>女</ns2:sex>
@XmlElement(nillable=true)//默认null值不显示在xml中,此设置为true,则null值也显示-><other xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
@XmlElement(required=true)?????
@XmlElement(defaultValue="others")????
3.@XmlAttribute
加载类属性上,默认是设置root的属性,可设置namepace和required属性等
4.@XmlValue
用于映射直接应用XML元素的文本内容的
5.@XmlType
用于定义在类上,表示该类对应于XML的一个复杂类型对象。默认情况下不加XmlType时我们的类也会自动的被映射为XML的一个复杂类型对象。使用@XmlType时主要是希望通过它的propOrder属性指定生成的XML的属性排列顺序,不指定顺序时默认生成的XML的节点/属性的顺序是不确定的
如:@XmlType(propOrder= { "name", "age"})
6.@XmlAccessorOrder
也是指定Java对象生成的XML元素/属性的顺序的。通过它指定的顺序的可选值有:
XmlAccessOrder.ALPHABETICAL:按照字母的自然顺序进行升序排列。
XmlAccessOrder.UNDEFINED:未定义,即顺序不固定,这个是默认值。
除了可以定义在类上,还可以定义在包上,定义在包上表示在该包中所有的类型对应的XML的默认排序规则。定义在包中时需要在对应的包下面建立package-info.java文件,然后将该注解加在package-info.java中的package声明上。如下我们就在com.xxx.jaxb的package-info.java中指定了com.xxx.jaxb包中的类对应的XML元素顺序默认按照字母升序排列。
@javax.xml.bind.annotation.XmlAccessorOrder(javax.xml.bind.annotation.XmlAccessOrder.ALPHABETICAL)
package com.xxx.jaxb;
7.@XmlTransient
用于在进行Java对象和XML相互转换时定义需要忽略的Java属性。
8.@XmlAccessorType
可以标注在Class和package上,标注在package上时需要标注在对应的package-info.java文件的package上。
作用:指定Java对象和XML相互转换时Java对象属性访问方式,即哪些属性会与XML进行映射。它的可选值是由XmlAccessType类型的枚举指定。一共四种:
- FIELD:会自动把非static、非transient和非XmlTransient标注的属性与XML进行映射,哪怕对应的属性是私有的。对应的get方法只有在使用了XmlElement等相关注解的情况下才会与XML映射。
- PROPERTY: 会自动把get/set配对的方法与XML进行映射。而使用类似于XmlElement这样的注解标注的get方法即使没有对应的set方法也会与XML进行映射。
- PUBLIC_MEMBER: 这是没有指定XmlAccessorType时的默认映射方式。没有使用XmlTransient标注的public类型的get/set方法对或没有使用transient修饰且没有使用XmlTransient注解标注的public类型的属性将自动与XML进行映射;其它属性或get/set方法如果使用了类似于XmlElement之类的注解进行标注也会自动与XML进行映射。
- NONE: 不自动将属性和get/set方法与XML进行映射。除非在对应的属性或get/set方法上使用了类似于XmlElement之类的JAXB注解进行标注。
9.@XmlElementWrapper
用于进行集合类型的属性映射时,在XML元素的外层再多包一层元素。可以指定name属性外,还可以指定namespace、required和nilable属性。
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private List<String> values = Arrays.asList("A", "B", "C");
}
生成的xml
<root>
<values>A</values>
<values>B</values>
<values>C</values>
</root>
设置xmlElementWrapper:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlElementWrapper
@XmlElement(name="value")
private List<String> values = Arrays.asList("A", "B", "C");
包裹后的xml
<root>
<items>
<value>A</value>
<value>B</value>
<value>C</value>
</items>
</root>
10. @XmlJavaTypeAdapter
用于自定义javabean和xml间字段转换的规则,比如date转为字符串,转为什么格式的等。
使用XmlJavaTypeAdapter时需要通过value属性指定一个XmlAdapter类,表示对应的适配器类。XmlAdapter是一个抽象类。其中定义了两个方法,marshal和unmarshal,marshal方法用于适配从Java到XML,unmarshal方法用于适配从XML到Java。比如需要把java.util.Date类型转换为yyyy-MM-dd格式的字符串可以定义如下适配器。
//适配器定义:
public class DateAdapter extends XmlAdapter<String, java.util.Date> {
private static final String PATTERN = "yyyy-MM-dd";
@Override
public Date unmarshal(String v) throws Exception {
if (v != null) {
return new SimpleDateFormat(PATTERN).parse(v);
}
return null;
}
@Override
public String marshal(Date v) throws Exception {
if (v != null) {
return new SimpleDateFormat(PATTERN).format(v);
}
return null;
}
}
//适配器使用:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlJavaTypeAdapter(DateAdapter.class)//value=DateAdapter.class
private Date date = new Date();
}
xml输出:
<root>
<date>2017-11-19</date>
</root>
XmlJavaTypeAdapter也可以标注在Java类上,表示遇到对应的类型时就使用指定的适配器
XmlJavaTypeAdapter也可以标注在package上,标注在package上时必须指定type类型,表示在指定的包中遇到type属性指定的类型时就使用value属性对应的适配器。下面的代码表示在com.xxx.jaxb中遇到java.util.Date类型就使用DateAdapter适配器。
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value=DateAdapter.class, type=java.util.Date.class)
package com.xxx.jaxb;
11.@XmlJavaTypeAdapters
只能标注在package上,用于定义多个XmlJavaTypeAdapters
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters({
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value = DateAdapter.class, type = java.util.Date.class),
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value = MoneyAdapter.class, type = java.math.BigDecimal.class) })
package com.xxx.jaxb;
12.@XmlAnyElement
用于不固定节点,如果有很多,可以用list<Object>来接收,默认创建的都是org.w3c.dom.Element类型的对象。动态节点有些是固定类型,可以设置@XmlAnyElement时指定其lax属性为true
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
public String no;
public String name;
@XmlAnyElement
public List<Object> others;
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
public String no;
public String name;
@XmlAnyElement(lax=true)
public List<Object> others;
@XmlRootElement(name="d1")
@XmlAccessorType(XmlAccessType.FIELD)
public static class D1 {
@XmlValue
public String value;
}
}
这样进行了unmarshal之后对应的others属性中就包含了一个D1类型的对象
@Test
public void testBasicUnmarshal() throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(Root.class, D1.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(this.getClass().getClassLoader().getResourceAsStream("jaxb/dynamic.xml"));
D1 d1 = null;
for (Object obj : root.others) {
if (obj instanceof D1) {
d1 = (D1) obj;
}
}
Assert.assertNotNull(d1);
}
13.@XmlElements
用于定义多个@XmlElement的,标注在集合类型的属性上以根据集合元素类型给定不同的元素名称。
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlElementWrapper(name = "objs")
@XmlElements({ @XmlElement(name = "string", type = String.class), @XmlElement(name = "int", type = Integer.class),
@XmlElement(name = "boolean", type = Boolean.class), @XmlElement(name = "long", type = Long.class) })
public List<Object> objs = Arrays.asList("A", 1, true, 1L);
}
14.更多
如XmlAnyAttribute,XmlElementRef,XmlElementRefs,XmlRegistry和XmlElementDecl,XmlID和XmlIDRef,XmlList,XmlSeeAlso,XmlEnum和XmlEnumValue。
http://doc.okbase.net/234390216/archive/296027.html
JAXB缺省的数据类型绑定
XML Schema类型 | Java数据类型 |
xsd:string | java.lang.String |
xsd:positiveInteger | java.math.BigInteger |
xsd:int | int |
xsd:long | long |
xsd:short | short |
xsd:decimal | java.math.BigDecimal |
xsd:float | float |
xsd:double | double |
xsd:boolean | boolean |
xsd:byte | byte |
xsd:QName | javax.xml.namespace.QName |
xsd:dateTime | javax.xml.datatype.XMLGregorianCalendar |
xsd:base64Binary | byte[] |
xsd:hexBinary | byte[] |
xsd:unsignedInt | long |
xsd:unsignedShort | int |
xsd:unsignedByte | short |
xsd:time | javax.xml.datatype.XMLGregorianCalendar |
xsd:date | javax.xml.datatype.XMLGregorianCalendar |
xsd:g | javax.xml.datatype.XMLGregorianCalendar |
xsd:anySimpleType | java.lang.Object |
xsd:anySimpleType | java.lang.String |
xsd:duration | javax.xml.datatype.Duration |
xsd:NOTATION | javax.xml.namespace.QName |