您的位置:首页 > 编程语言 > Java开发

Jaxb2 转换XML文档——完成Java对象和XML相互转换

2013-06-24 21:14 344 查看

Jaxb2转换XML文档——完成Java对象和XML相互转换

这次介绍Jaxb2完成xml的转换,Jaxb2使用了JDK的新特性。如:Annotation、GenericType等,Jaxb2需要在即将转换的JavaBean中添加annotation注解。下面我们就来看看Jaxb2是怎么样完成Java对象到XML之间的相互转换吧。

一、准备工作

1、资源准备

a)官方文档:http://www.oracle.com/technetwork/articles/javase/index-140168.html

b)Jar包下载:http://jaxb.java.net/2.2.3/JAXB2_20101209.jar

如果你有添加jdk的jar到工程中,在rt.jar中就带有jaxb2。一般情况下不用自己添加jaxb2的jar。

2、程序前代码准备

packagecom.hoo.test;


importjava.io.IOException;

importjava.io.StringReader;

importjava.io.StringWriter;

importjava.util.ArrayList;

importjava.util.HashMap;

importjava.util.List;

importjava.util.Map;

importjavax.xml.bind.JAXBContext;

importjavax.xml.bind.JAXBException;

importjavax.xml.bind.Marshaller;

importjavax.xml.bind.Unmarshaller;

importorg.junit.After;

importorg.junit.Before;

importorg.junit.Test;

importcom.hoo.entity.Account;

importcom.hoo.entity.AccountBean;

importcom.hoo.entity.Birthday;

importcom.hoo.entity.ListBean;

importcom.hoo.entity.MapBean;


/**

*function:Jaxb2完成Java和XML的编组、解组

*@authorhoojo

*@createDate2011-4-25上午11:54:06

*@fileJaxb2Test.java

*@packagecom.hoo.test

*@projectWebHttpUtils

*@blog'target='_blank'>http://blog.csdn.net/IBM_hoojo[/code]
*@emailhoojo_@126.com

*@version1.0

*/

publicclassJaxb2Test{

privateJAXBContextcontext=null;


privateStringWriterwriter=null;

privateStringReaderreader=null;


privateAccountBeanbean=null;


@Before

publicvoidinit(){

bean=newAccountBean();

bean.setAddress("北京");

bean.setEmail("email");

bean.setId(1);

bean.setName("jack");

Birthdayday=newBirthday();

day.setBirthday("2010-11-22");

bean.setBirthday(day);


try{

context=JAXBContext.newInstance(AccountBean.class);

}catch(Exceptione){

e.printStackTrace();

}

}


@After

publicvoiddestory(){

context=null;

bean=null;

try{

if(writer!=null){

writer.flush();

writer.close();

}

if(reader!=null){

reader.close();

}

}catch(IOExceptione){

e.printStackTrace();

}

System.gc();

}


publicvoidfail(Objecto){

System.out.println(o);

}


publicvoidfailRed(Objecto){

System.err.println(o);

}

}


通过JAXBContext的newInstance方法,传递一个class就可以获得一个上下文。newInstance方法也可以传递一个xml的文件的path。通过xml文件,对class的描述进行转换。然后,就可以通过这个上下文的来创建一个Marshaller,通过Marshaller对象的marshal方法就可以转换JavaBean对象到xml。同样JAXBContext也可以创建一个Unmarshall的unmarshal方法可以进行xml到Java对象的解组。

二、对Java编组、XML解组

1、JavaBean和XML的相互转换

代码如下:

@Test

publicvoidtestBean2XML(){

try{

//下面代码演示将对象转变为xml

Marshallermar=context.createMarshaller();

writer=newStringWriter();

mar.marshal(bean,writer);

fail(writer);


//下面代码演示将上面生成的xml转换为对象

reader=newStringReader(writer.toString());

Unmarshallerunmar=context.createUnmarshaller();

bean=(AccountBean)unmar.unmarshal(reader);

fail(bean);

}catch(JAXBExceptione){

e.printStackTrace();

}

}


上面的context是在init方法中创建的,它传递了一个AccountBean的class,这个AccountBean不是一般的普通的bean。除了它带有getter、setter方法外,还有Annotation注解。下面我们就看看这个bean的代码。

packagecom.hoo.entity;


importjavax.xml.bind.annotation.XmlAttribute;

importjavax.xml.bind.annotation.XmlRootElement;

importcom.sun.xml.internal.txw2.annotation.XmlElement;


@XmlRootElement(name="account")

publicclassAccountBean{

privateintid;

privateStringname;

privateStringemail;

privateStringaddress;

privateBirthdaybirthday;


@XmlElement

publicBirthdaygetBirthday(){

returnbirthday;

}

publicvoidsetBirthday(Birthdaybirthday){

this.birthday=birthday;

}


@XmlAttribute(name="number")

publicintgetId(){

returnid;

}

publicvoidsetId(intid){

this.id=id;

}


@XmlElement

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}


@XmlElement

publicStringgetEmail(){

returnemail;

}

publicvoidsetEmail(Stringemail){

this.email=email;

}


@XmlElement

publicStringgetAddress(){

returnaddress;

}

publicvoidsetAddress(Stringaddress){

this.address=address;

}


@Override

publicStringtoString(){

returnthis.name+"#"+this.id+"#"+this.address+"#"+this.birthday+"#"+this.email;

}

}


上面的XmlRootElement是设置当前对象转换成xml后的根节点,name的值是设置根节点的名称。在getter方法上设置XmlElement表示这个方法对应的属性是一个xml元素,如果这个注解还设置了name,那么这个name就是转换后xml的名称。在一个属性上设置XmlAttribute,表示这个方法对应的属性在转换xml后是父元素的一个属性。XmlAttribute的name就是转换后xml的属性的name。

运行后,结果如下:

<?xmlversion="1.0"encoding="UTF-8"standalone="yes"?><accountnumber="1"><address>北京</address>

<birthday><birthday>2010-11-22</birthday></birthday><email>email</email><name>jack</name></account>

jack#1#北京#2010-11-22#email


把转换后的xml和上面的AccountBean对应看看

2、对List类型对象,进行编组、解组

@Test

publicvoidtestList2XML(){

ListBeanlistBean=newListBean();

listBean.setName("listtoxml");

List<Object>list=newArrayList<Object>();

list.add(bean);

bean=newAccountBean();

bean.setAddress("china");

bean.setEmail("tom@125.com");

bean.setId(2);

bean.setName("tom");

Birthdayday=newBirthday("2010-11-22");

bean.setBirthday(day);


Accountacc=newAccount();

acc.setAddress("china");

acc.setEmail("tom@125.com");

acc.setId(2);

acc.setName("tom");

day=newBirthday("2010-11-22");

acc.setBirthday(day);

list.add(bean);

list.add(acc);

listBean.setList(list);


try{

context=JAXBContext.newInstance(ListBean.class);

//下面代码演示将对象转变为xml

Marshallermar=context.createMarshaller();

writer=newStringWriter();

mar.marshal(listBean,writer);

fail(writer);


//下面代码演示将上面生成的xml转换为对象

reader=newStringReader(writer.toString());

Unmarshallerunmar=context.createUnmarshaller();

listBean=(ListBean)unmar.unmarshal(reader);

fail(listBean.getList().get(0));

fail(listBean.getList().get(1));

fail(listBean.getList().get(2));

}catch(JAXBExceptione){

e.printStackTrace();

}

}


你不能直接new一个List,然后将对象放到List中。进行编组、解组,这样会出现异常情况的。你需要构建一个JavaBean,在bean中创建一个List的属性。然后在这个属性的getter方法上进行Annotation注解。下面我们看看ListBean的代码:

packagecom.hoo.entity;


importjava.util.List;

importjavax.xml.bind.annotation.XmlAttribute;

importjavax.xml.bind.annotation.XmlElement;

importjavax.xml.bind.annotation.XmlElements;

importjavax.xml.bind.annotation.XmlRootElement;


@SuppressWarnings("unchecked")

@XmlRootElement(name="list-bean")

publicclassListBean{

privateStringname;

privateListlist;


@XmlElements({

@XmlElement(name="account",type=Account.class),

@XmlElement(name="bean",type=AccountBean.class)

})

publicListgetList(){

returnlist;

}


publicvoidsetList(Listlist){

this.list=list;

}


@XmlAttribute

publicStringgetName(){

returnname;

}


publicvoidsetName(Stringname){

this.name=name;

}

}


XmlElements表示是一个集合类型,然后注解在集合中存放上面类型的对象。

XmlElement表示在集合中存放的一个对象类型和元素名称。

转换后结果如下:

<?xmlversion="1.0"encoding="UTF-8"standalone="yes"?>

<list-beanname="listtoxml">

<beannumber="1"><address>北京</address><birthday><birthday>2010-11-22</birthday></birthday>

<email>email</email><name>jack</name></bean>

<beannumber="2"><address>china</address><birthday><birthday>2010-11-22</birthday></birthday>

<email>tom@125.com</email><name>tom</name></bean>

<account><address>china</address><birthday><birthday>2010-11-22</birthday></birthday>

<email>tom@125.com</email><id>2</id><name>tom</name></account>

</list-bean>

jack#1#北京#2010-11-22#email

tom#2#china#2010-11-22#tom@125.com

2#tom#tom@125.com#china#2010-11-22


转换后的XML和Bean的注解的描述是一样的吧。

2、对Map集合进行解组、编组

/**

*<b>function:</b>Map需要自己实现,可以构造一个简单的Map对象实现

*'target='_blank'>http://metro.1045641.n5.nabble.com/Does-JAXB-2-0-support-Map-td1058084.html[/code]
*@authorhoojo

*@createDate2010-12-1上午10:23:26

*/

@Test

publicvoidtestMap2XML(){

MapBeanmapBean=newMapBean();

HashMap<String,AccountBean>map=newHashMap<String,AccountBean>();

map.put("NO1",bean);

bean=newAccountBean();

bean.setAddress("china");

bean.setEmail("tom@125.com");

bean.setId(2);

bean.setName("tom");

Birthdayday=newBirthday("2010-11-22");

bean.setBirthday(day);

map.put("NO2",bean);

mapBean.setMap(map);


try{

context=JAXBContext.newInstance(MapBean.class);

//下面代码演示将对象转变为xml

Marshallermar=context.createMarshaller();

writer=newStringWriter();

mar.marshal(mapBean,writer);

fail(writer);


//下面代码演示将上面生成的xml转换为对象

reader=newStringReader(writer.toString());

Unmarshallerunmar=context.createUnmarshaller();

mapBean=(MapBean)unmar.unmarshal(reader);

fail(mapBean.getMap());

}catch(JAXBExceptione){

e.printStackTrace();

}

}


下面看看MapBean的代码

packagecom.hoo.entity;


importjava.util.HashMap;

importjavax.xml.bind.annotation.XmlRootElement;

importjavax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

importcom.hoo.util.MapAdapter;


@XmlRootElement

publicclassMapBean{

privateHashMap<String,AccountBean>map;


@XmlJavaTypeAdapter(MapAdapter.class)

publicHashMap<String,AccountBean>getMap(){

returnmap;

}

publicvoidsetMap(HashMap<String,AccountBean>map){

this.map=map;

}

}


上面的map集合的getter方法有一个XmlJavaTypeAdapter,需要传递一个Adapter的类型。

下面看看MyAdapter的代码

packagecom.hoo.util;


importjava.util.HashMap;

importjava.util.Map;

importjavax.xml.bind.annotation.adapters.XmlAdapter;

importcom.hoo.entity.AccountBean;


/**

*<b>function:</b>AccountBean编组、解组的XmlAdapter

*@authorhoojo

*@createDate2011-4-25下午05:03:18

*@fileMyAdetper.java

*@packagecom.hoo.util

*@projectWebHttpUtils

*@blog'target='_blank'>http://blog.csdn.net/IBM_hoojo[/code]
*@emailhoojo_@126.com

*@version1.0

*/

publicclassMapAdapterextendsXmlAdapter<MapElements[],Map<String,AccountBean>>{

publicMapElements[]marshal(Map<String,AccountBean>arg0)throwsException{

MapElements[]mapElements=newMapElements[arg0.size()];


inti=0;

for(Map.Entry<String,AccountBean>entry:arg0.entrySet())

mapElements[i++]=newMapElements(entry.getKey(),entry.getValue());


returnmapElements;

}


publicMap<String,AccountBean>unmarshal(MapElements[]arg0)throwsException{

Map<String,AccountBean>r=newHashMap<String,AccountBean>();

for(MapElementsmapelement:arg0)

r.put(mapelement.key,mapelement.value);

returnr;

}

}


MapElements

packagecom.hoo.util;


importjavax.xml.bind.annotation.XmlElement;

importcom.hoo.entity.AccountBean;


/**

*<b>function:</b>MapElements

*@authorhoojo

*@createDate2011-4-25下午05:04:04

*@fileMyElements.java

*@packagecom.hoo.util

*@projectWebHttpUtils

*@blog'target='_blank'>http://blog.csdn.net/IBM_hoojo[/code]
*@emailhoojo_@126.com

*@version1.0

*/

publicclassMapElements{

@XmlElement

publicStringkey;


@XmlElement

publicAccountBeanvalue;


@SuppressWarnings("unused")

privateMapElements(){

}//RequiredbyJAXB


publicMapElements(Stringkey,AccountBeanvalue){

this.key=key;

this.value=value;

}

}


运行结果如下:

<?xmlversion="1.0"encoding="UTF-8"standalone="yes"?><mapBean><map><item><key>NO2</key><valuenumber="2"><address>china</address>

<birthday><birthday>2010-11-22</birthday></birthday><email>tom@125.com</email><name>tom</name></value></item>

<item><key>NO1</key><valuenumber="1"><address>北京</address><birthday><birthday>2010-11-22</birthday></birthday>

<email>email</email><name>jack</name></value></item></map></mapBean>

{NO2=tom#2#china#2010-11-22#tom@125.com,NO1=jack#1#北京#2010-11-22#email}


作者:hoojo

出处:http://www.cnblogs.com/hoojo/archive/2011/04/26/2029011.html

blog:http://blog.csdn.net/IBM_hoojo

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: