jaxb实现javabean和xml间互相转换

本文介绍JAXB(Java Architecture for XML Binding)的基本用法,包括JavaBean与XML之间的相互转换过程,以及各种注解的详细解释。还介绍了如何自定义转换规则,并列举了一些常用的数据类型绑定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值