xml java jaxb_【Java】JAXB操作XML用法详解

什么是JAXB?

JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。在JAX-WS(Java的WebService规范之一)中,JAXB可以实现对象和XML之间相互转换。Unmarshaller类管理将XML数据反序列化为新创建的Java内容树的进程,并可在解组时有选择的验证XML数据。Marshaller类负责管理将Java内容树序列化回XML数据的过程。

bc7fdfc03a181785f939cc7c3cabcadc.gif

在JDK1.6时,JAXB 2.0是JDK 1.6的组成部分。JAXB 2.2.3是JDK 1.7的组成部分。

JDK中JAXB相关的重要Class和Interface

1、JAXBContext类,是应用的入口,用于管理XML/Java绑定信息。

2、Marshaller接口,将Java对象序列化为XML数据。

3、Unmarshaller接口,将XML数据反序列化为Java对象。

JDK中JAXB相关的重要Annotation注解

1、@XmlRootElement

说明:将类或枚举类型映射到XML元素,这是xml的入口,根节点,要记得在声明

范围:顶层类,枚举类型

属性说明:name: XML元素的本地名称,namespace: XML元素的名称空间名

2、@XmlElement

说明:将JavaBean属性映射到派生于属性节点名称的XML元素

范围:JavaBean属性、非static(静态)、非transient(瞬时)字段、XmlElements中的程序元素

属性说明:defaultValue:此元素的默认值,

name:xml模式元素的名称,

namespace:xml模式元素的xml目标名称空间,

nillable:是否可以为空,默认false,

required:如果 required() 为 true,则将 Javabean 属性映射到一个 minOccurs="1" 的 XML 模式元素声明。maxOccurs 为 "1" 表示单个赋值的属性,maxOccurs 为 "unbounded" 则表示多个赋值的属性;如果 required() 为 false,则将 Javabean 属性映射到一个 minOccurs="0" 的 XML 模式元素声明。

注意:

如果只有属性,没有get/set方法,xml是不会输出该节点的,需要在属性上设置@XmlElement,如果有get方法要要在get上设置@XmlElement,不然会异常。

3、@XmlElements

说明:多个@XmlElement注解的容器,此注解用于注释JavaBean集合属性(如列表)

属性说明:value:@XmlElement注解集合

例如@XmlElementWrapper(name="DEGREES")

@XmlElements({

@XmlElement(name="Degree",type=Degrees.class),

@XmlElement(name="b",type=String.class)

})

private List degrees;

4、@XmlAttribute

说明:将JavaBean属性映射到XML属性

范围:JavaBean属性、字段

5、@XmlAccessorType

定义映射这个类中的何种类型需要映射到XML。可接收四个参数,分别是:XmlAccessType.FIELD:映射这个类中的所有字段到XML,不需要get/set方法,否则会报错

XmlAccessType.PROPERTY:映射这个类中的属性(get/set方法)到XML,如果没有初始值 或 没有get/set方法,xml不会输出

XmlAccessType.PUBLIC_MEMBER:将这个类中的所有public的field或property同时映射到XML(默认) ,只输出public修饰符的属性,或者是其他修饰符,但必须有 get/set方法

XmlAccessType.NONE:不映射,不输出任何字段内容

6、@XmlTransient

定义某一字段或属性不需要被映射为XML。如当一个类的XmlAccessorType被标注为PROPERTY时,在某一get/set方法的字段上标注此注解,那么该属性则不会被映射。

注意:

测试发现只能设置单独在某一属性出现,不能和其他注解同时存在,否则会发生异常

7、@XmlType

定义映射的一些相关规则propOrder:指定映射XML时的节点顺序,默认是随机的顺序

factoryClass:指定UnMarshal时生成映射类实例所需的工厂类,默认为这个类本身

factoryMethod:指定工厂类的工厂方法

name:定义XML Schema中type的名称  (对应的xsd文件中的type)

namespace:指定Schema中的命名空间

8、@XmlAccessorOrder

控制JAXB 绑定类中属性和字段的排序。其value属性,它有两个属性值:XmlAccessOrder.ALPHABETICAL:对生成的xml元素按字母书序排序,满足基本需求这样就不需要使用propOrder一个个字母排序了

XmlAccessOrder.UNDEFINED:不排序

9、@XmlElementWrapper

为数组元素或集合元素定义一个父节点。

如,类中有一元素为List items,若不加此注解,该元素将被映射为...

...

设置完@XmlElementWrapper后会生成这样的XML样式:

...

...

10、@XmlJavaTypeAdapter

使用定制的适配器(即扩展抽象类XmlAdapter并覆盖marshal()和unmarshal()方法),以序列化Java类为XML。

比如下面例子对日期格式进行特殊的处理,需要继承xmladapter,从date类型转成string类型@XmlJavaTypeAdapter(value=JaxbAdapter.class)

private Date date;

...

public class JaxbAdapter extends XmlAdapter {

@Override

public Date unmarshal(String v) throws Exception {

return null;

}

@Override

public String marshal(Date v) throws Exception {

SimpleDateFormat simple = new SimpleDateFormat("yyyy/MM/dd");

return simple.format(v);

}

}

排序

默认情况下,Jaxb编组出来的xml中的字段顺序是随机的,你可以使用@XmlType的propOrder属性来指定序列化的顺序。

第一步:定义java类时,使用@XmlType(propOrder = { "id", "name", "age","book"})指定输出顺序。

bc7fdfc03a181785f939cc7c3cabcadc.gif

注意:

1.对于@XmlElementWrapper标注的属性,不能出现在@XmlType的propOrder列表中。

2.对于所有@XmlElement标注过的属性,必须出现在@XmlType的propOrder列表中。

测试源码import java.io.StringReader;

import java.io.StringWriter;

import java.util.ArrayList;

import java.util.List;

import javax.xml.bind.JAXBContext;

import javax.xml.bind.JAXBException;

import javax.xml.bind.Marshaller;

import javax.xml.bind.Unmarshaller;

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlAttribute;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlElementWrapper;

import javax.xml.bind.annotation.XmlRootElement;

import javax.xml.bind.annotation.XmlType;

import javax.xml.bind.annotation.XmlValue;

import net.sf.json.JSONObject;

public class XMLTest3 {

@XmlRootElement(name = "xml")

@XmlAccessorType(XmlAccessType.PROPERTY)

@XmlType

static class A{

private B b;

private C c;

private List d;

@XmlElement(name = "B")

public B getB() {

return b;

}

public void setB(B b) {

this.b = b;

}

public C getC() {

return c;

}

public void setC(C c) {

this.c = c;

}

// 为数组元素或集合元素定义一个父节点

@XmlElementWrapper(name="Dlist")

@XmlElement(name="d")

public List getD() {

return d;

}

public void setD(List d) {

this.d = d;

}

}

static class B {

private String b1;

private String b2;

@XmlAttribute

public String getB1() {

return b1;

}

public void setB1(String b1) {

this.b1 = b1;

}

@XmlValue

public String getB2() {

return b2;

}

public void setB2(String b2) {

this.b2 = b2;

}

}

static class C {

private String c1;

private String c2="";  //想要将空值的xml节点输出来,请将该属性初始化一个空值

public String getC1() {

return c1;

}

public void setC1(String c1) {

this.c1 = c1;

}

public String getC2() {

return c2;

}

public void setC2(String c2) {

this.c2 = c2;

}

}

static class D {

private String d1;

private String d2;

D(){}

D(String d1,String d2){

this.d1 = d1;

this.d2 = d2;

}

public String getD1() {

return d1;

}

public void setD1(String d1) {

this.d1 = d1;

}

public String getD2() {

return d2;

}

public void setD2(String d2) {

this.d2 = d2;

}

}

public static void main(String[] args) throws JAXBException {

A a = new A();

B b = new B();

b.setB1("B1");

b.setB2("B2");

a.setB(b);

C c = new C();

c.setC1("C1");

a.setC(c);

List list = new ArrayList<>();

list.add(new D("d1","d2"));

list.add(new D("d1","d2"));

a.setD(list);

// 构造报文 XML 字符串

String xmlStr = object2Xml(a);

System.out.println(xmlStr);

// XML字符串转JavaBean对象

A a2 = xml2Object(xmlStr, A.class);

System.out.println(a.getB().getB1());

// 不能使用JSONObject, 会有找不到内部类get/set方法异常,解决方法是将内部类提出来

//      System.out.println(JSONObject.fromObject(a2));

}

/**

* @param object 对象

* @return 返回xmlStr

*/

public static String object2Xml(Object object) {

try {

StringWriter writer = new StringWriter();

JAXBContext context = JAXBContext.newInstance(object.getClass());

Marshaller marshal = context.createMarshaller();

marshal.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 格式化输出

marshal.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");// 编码格式,默认为utf-8

marshal.setProperty(Marshaller.JAXB_FRAGMENT, false);// 是否省略xml头信息

marshal.setProperty(Marshaller.JAXB_ENCODING, "utf-8");

marshal.marshal(object, writer);

return new String(writer.getBuffer());

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

/**

* @param xmlStr 字符串

* @param c 对象Class类型

* @return 对象实例

*/

@SuppressWarnings("unchecked")

public static  T xml2Object(String xmlStr,Class c) {

try {

JAXBContext context = JAXBContext.newInstance(c);

Unmarshaller unmarshaller = context.createUnmarshaller();

return (T) unmarshaller.unmarshal(new StringReader(xmlStr));

} catch (JAXBException e) {  e.printStackTrace();  return null; }

}

}

结果

B2

C1

d1

d2

d1

d2

B1

常见异常com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions

If a class has @XmlElement property, it cannot have @XmlValue property.

this problem is related to the following location:

at public java.lang.String com.chinatelecom.web.trade.demo.XMLTest3$B.getB2()

at com.chinatelecom.web.trade.demo.XMLTest3$B

at public com.chinatelecom.web.trade.demo.XMLTest3$B com.chinatelecom.web.trade.demo.XMLTest3$A.getB()

at com.chinatelecom.web.trade.demo.XMLTest3$A

异常解读

遇到此类问题其实很好理解,一个类中是不允许@XmlElement和 @XmlValue两个注解同时存在的,当然也不允许有多个@XmlValue,你肯定没见过生成的格式是下面这种情况,虽然这两个不允许同时存在,但是可以多个@XmlAttribute和一个@XmlValue

B3

B2

XmlAccessType API:

相关阅读:json和xml操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值