Dom4j 操作XML

最后更新于:2022-04-01 14:22:35

Dom4j也可以很方便完成XML文档的创建、元素的修改、文档的查询遍历等,但dom4j稍比jdom复杂一点,不过在大片文档的情况下dom4j的性能要不jdom好。 ### 准备 首先,提供相关的jar包 Dom4jjar包下载: [http://sourceforge.net/projects/dom4j/files/dom4j-2.0.0-ALPHA-2/](http://sourceforge.net/projects/dom4j/files/dom4j-2.0.0-ALPHA-2/) jaxenjar下载: [http://repo1.maven.org/maven2/jaxen/jaxen/1.1.1/jaxen-1.1.1.jar](http://repo1.maven.org/maven2/jaxen/jaxen/1.1.1/jaxen-1.1.1.jar) 和dom4j依赖或相关的jar: [http://dom4j.sourceforge.net/dependencies.html](http://dom4j.sourceforge.net/dependencies.html) Junit-jar下载: [http://ebr.springsource.com/repository/app/bundle/version/download?name=com.springsource.org.junit&version=4.8.1&type=binary](http://ebr.springsource.com/repository/app/bundle/version/download?name=com.springsource.org.junit&version=4.8.1&type=binary)   其次,准备测试案例的部分代码: ~~~ package com.hoo.test; import java.io.File; import java.util.Iterator; import java.util.List; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.QName; import org.dom4j.dom.DOMAttribute; import org.dom4j.io.SAXReader; import org.dom4j.tree.BaseElement; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * <b>function:</b> 使用Dom4j操作XML * @author hoojo * @createDate 2011-8-5 下午06:15:40 * @file DocumentTest.java * @package com.hoo.test * @project Dom4jTest * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class DocumentTest { private SAXReader reader = null; @Before public void init() { reader = new SAXReader(); } @After public void destory() { reader = null; System.gc(); } public void fail(Object o) { if (o != null) System.out.println(o); } } ~~~ ### 创建一篇XML文档 文档格式如下: ~~~ <?xml version="1.0" encoding="UTF-8"?> <catalog> <!--An XML Catalog--> <?target instruction?> <journal title="XML Zone" publisher="IBM developerWorks"> <article level="Intermediate" date="December-2001"> <title>Java configuration with XML Schema</title> <author> <firstname>Marcello</firstname> <lastname>Vitaletti</lastname> </author> </article> </journal> </catalog> ~~~ 创建文档代码如下: ~~~ /** * <b>function:</b>创建文档 * @author hoojo * @createDate 2011-8-5 下午06:18:18 */ @Test public void createDocument() { //创建一篇文档 Document doc = DocumentHelper.createDocument(); //添加一个元素 Element root = doc.addElement("catalog"); //为root元素添加注释 root.addComment("An XML Catalog"); //添加标记 root.addProcessingInstruction("target", "instruction"); //创建元素 Element journalEl = new BaseElement("journal"); //添加属性 journalEl.addAttribute("title", "XML Zone"); journalEl.addAttribute("publisher", "IBM developerWorks"); root.add(journalEl); //添加元素 Element articleEl = journalEl.addElement("article"); articleEl.addAttribute("level", "Intermediate"); articleEl.addAttribute("date", "December-2001"); Element titleEl = articleEl.addElement("title"); //设置文本内容 titleEl.setText("Java configuration with XML Schema"); //titleEl.addText("Java configuration with XML Schema"); Element authorEl = articleEl.addElement("author"); authorEl.addElement("firstname").setText("Marcello"); authorEl.addElement("lastname").addText("Vitaletti"); //可以使用 addDocType() 方法添加文档类型说明。 doc.addDocType("catalog", null,"file://c:/Dtds/catalog.dtd"); fail(doc.getRootElement().getName()); //将xml转换成文本 fail(doc.asXML()); //写入到文件 /*XMLWriter output; try { output = new XMLWriter(new FileWriter(new File("file/catalog.xml"))); output.write(doc); output.close(); } catch (IOException e) { e.printStackTrace(); }*/ } ~~~ DocumentHelper是一个文档助手类(工具类),它可以完成文档、元素、文本、属性、注释、CDATA、Namespace、XPath的创建,以及利用XPath完成文档的遍历和将文本转换成Document; parseText完成将xml字符串转换成Doc的功能 <table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">Document doc = DocumentHelper.parseText("&lt;root&gt;&lt;/root&gt;");</span></p></td></tr></tbody></table>   createDocument创建一个文档 <table border="1" cellpadding="0" cellspacing="0" height="32" width="359"><tbody><tr><td valign="top"><p><span style="font-size:13px">Document doc = DocumentHelper.createDocument();</span></p></td></tr></tbody></table> 如果带参数就会创建一个带有根元素的文档 createElement创建一个元素 <table border="1" cellpadding="0" cellspacing="0" height="32" width="357"><tbody><tr><td valign="top"><p><span style="font-size:13px">Element el = DocumentHelper.createElement("el");</span></p></td></tr></tbody></table> Document的addElement方法可以给当前文档添加一个子元素 <table border="1" cellpadding="0" cellspacing="0" height="32" width="355"><tbody><tr><td valign="top"><p><span style="font-size:13px">Element root = doc.addElement("catalog");</span></p></td></tr></tbody></table> addComment方法可以添加一段注释 <table border="1" cellpadding="0" cellspacing="0" height="32" width="351"><tbody><tr><td valign="top"><p><span style="font-size:13px">root.addComment("An XML Catalog");</span></p></td></tr></tbody></table> 为root元素添加一段注释 addProcessingInstruction添加一个标记 <table border="1" cellpadding="0" cellspacing="0" height="32" width="348"><tbody><tr><td valign="top"><p><span style="font-size:13px">root.addProcessingInstruction("target", "instruction");</span></p></td></tr></tbody></table> 为root元素添加一个标记 newBaseElement可以创建一个元素 <table border="1" cellpadding="0" cellspacing="0" height="32" width="350"><tbody><tr><td valign="top"><p><span style="font-size:13px">Element journalEl = new BaseElement("journal");</span></p></td></tr></tbody></table> addAttribute添加属性 <table border="1" cellpadding="0" cellspacing="0" height="32" width="350"><tbody><tr><td valign="top"><p><span style="font-size:13px">journalEl.addAttribute("title", "XML Zone");</span></p></td></tr></tbody></table> add添加一个元素 <table border="1" cellpadding="0" cellspacing="0" height="32" width="349"><tbody><tr><td valign="top"><p><span style="font-size:13px">root.add(journalEl);</span></p></td></tr></tbody></table> 将journalEl元素添加到root元素中 addElement添加一个元素,并返回当前元素 <table border="1" cellpadding="0" cellspacing="0" height="32" width="346"><tbody><tr><td valign="top"><p><span style="font-size:13px">Element articleEl = journalEl.addElement("article");</span></p></td></tr></tbody></table> 给journalEl元素添加一个子元素article setText、addText可以设置元素的文本 <table border="1" cellpadding="0" cellspacing="0" height="56" width="349"><tbody><tr><td valign="top"><p><span style="font-size:13px">authorEl.addElement("firstname").setText("Marcello");</span></p><p><span style="font-size:13px">authorEl.addElement("lastname").addText("Vitaletti");</span></p></td></tr></tbody></table> addDocType可以设置文档的DOCTYPE <table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">doc.addDocType("catalog", null,"file://c:/Dtds/catalog.dtd");</span></p></td></tr></tbody></table> asXML可以将文档或元素转换成一段xml字符串 <table border="1" cellpadding="0" cellspacing="0" height="56" width="344"><tbody><tr><td valign="top"><p><span style="font-size:13px">doc.asXML();</span></p><p><span style="font-size:13px">root.asXML();</span></p></td></tr></tbody></table> XMLWriter类可以把文档写入到文件中 <table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">output = new XMLWriter(new FileWriter(new File("file/catalog.xml")));</span></p><p><span style="font-size:13px">output.write(doc);</span></p><p><span style="font-size:13px">output.close();</span></p></td></tr></tbody></table> ### 修改XML文档内容 ~~~ /** * <b>function:</b> 修改XML内容 * @author hoojo * @createDate 2011-8-9 下午03:37:04 */ @SuppressWarnings("unchecked") @Test public void modifyDoc() { try { Document doc = reader.read(new File("file/catalog.xml")); //修改属性内容 List list = doc.selectNodes("//article/@level"); Iterator<Attribute> iter = list.iterator(); while (iter.hasNext()) { Attribute attr = iter.next(); fail(attr.getName() + "#" + attr.getValue() + "#" + attr.getText()); if ("Intermediate".equals(attr.getValue())) { //修改属性值 attr.setValue("Introductory"); fail(attr.getName() + "#" + attr.getValue() + "#" + attr.getText()); } } list = doc.selectNodes("//article/@date"); iter = list.iterator(); while (iter.hasNext()) { Attribute attr = iter.next(); fail(attr.getName() + "#" + attr.getValue() + "#" + attr.getText()); if ("December-2001".equals(attr.getValue())) { //修改属性值 attr.setValue("December-2011"); fail(attr.getName() + "#" + attr.getValue() + "#" + attr.getText()); } } //修改节点内容 list = doc.selectNodes("//article"); Iterator<Element> it = list.iterator(); while (it.hasNext()) { Element el = it.next(); fail(el.getName() + "#" + el.getText() + "#" + el.getStringValue()); //修改title元素 Iterator<Element> elIter = el.elementIterator("title"); while(elIter.hasNext()) { Element titleEl = elIter.next(); fail(titleEl.getName() + "#" + titleEl.getText() + "#" + titleEl.getStringValue()); if ("Java configuration with XML Schema".equals(titleEl.getTextTrim())) { //修改元素文本值 titleEl.setText("Modify the Java configuration with XML Schema"); fail(titleEl.getName() + "#" + titleEl.getText() + "#" + titleEl.getStringValue()); } } } //修改节点子元素内容 list = doc.selectNodes("//article/author"); it = list.iterator(); while (it.hasNext()) { Element el = it.next(); fail(el.getName() + "#" + el.getText() + "#" + el.getStringValue()); List<Element> childs = el.elements(); for (Element e : childs) { fail(e.getName() + "#" + e.getText() + "#" + e.getStringValue()); if ("Marcello".equals(e.getTextTrim())) { e.setText("Ayesha"); } else if ("Vitaletti".equals(e.getTextTrim())) { e.setText("Malik"); } fail(e.getName() + "#" + e.getText() + "#" + e.getStringValue()); } } //写入到文件 /*XMLWriter output = new XMLWriter(new FileWriter(new File("file/catalog-modified.xml"))); output.write(doc); output.close();*/ } catch (DocumentException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } ~~~ reader.read(new File("file/catalog.xml"));读取指定xml文件内容到文档中; selectNodes是XPath的查询方法,完成xml文档的查询,传递xpath路径。其使用方法可以参考jdom的xpath的使用方法:[http://www.cnblogs.com/hoojo/archive/2011/08/11/2134638.html](http://www.cnblogs.com/hoojo/archive/2011/08/11/2134638.html) getName获取元素标签名称、getValue、getText获取值、文本内容; elementIterator("title");获取当前节点下所有的title元素,返回Iterator; elements获取下面所有的子元素,返回的是一个集合List; ### 显示文档相关信息 ~~~ private String format(int i) { String temp = ""; while (i > 0) { temp += "--"; i--; } return temp; } /** * <b>function:</b>递归显示文档内容 * @author hoojo * @createDate 2011-8-9 下午03:43:45 * @param i * @param els */ private void print(int i, List<Element> els) { i++; for (Element el : els) { fail(format(i) + "##" + el.getName() + "#" + el.getTextTrim()); if (el.hasContent()) { print(i, el.elements()); } } } /** * <b>function:</b>显示文档相关信息 * @author hoojo * @createDate 2011-8-9 下午03:44:10 */ @Test public void printInfo() { try { Document doc = reader.read(new File("file/catalog.xml")); fail("asXML: " + doc.asXML()); fail(doc.asXPathResult(new BaseElement("article"))); List<Node> list = doc.content(); for (Node node : list) { fail("Node: " + node.getName() + "#" + node.getText() + "#" + node.getStringValue()); } fail("-----------------------------"); print(0, doc.getRootElement().elements()); fail("getDocType: " + doc.getDocType()); fail("getNodeTypeName: " + doc.getNodeTypeName()); fail("getPath: " + doc.getRootElement().getPath()); fail("getPath: " + doc.getRootElement().getPath(new BaseElement("journal"))); fail("getUniquePath: " + doc.getRootElement().getUniquePath()); fail("getXMLEncoding: " + doc.getXMLEncoding()); fail("hasContent: " + doc.hasContent()); fail("isReadOnly: " + doc.isReadOnly()); fail("nodeCount: " + doc.nodeCount()); fail("supportsParent: " + doc.supportsParent()); } catch (DocumentException e) { e.printStackTrace(); } fail("getEncoding: " + reader.getEncoding()); fail("isIgnoreComments: " + reader.isIgnoreComments()); fail("isMergeAdjacentText: " + reader.isMergeAdjacentText()); fail("isStringInternEnabled: " + reader.isStringInternEnabled()); fail("isStripWhitespaceText: " + reader.isStripWhitespaceText()); fail("isValidating: " + reader.isValidating()); } ~~~ ### 删除文档内容 ~~~ /** * <b>function:</b> 删除节点内容 * @author hoojo * @createDate 2011-8-9 下午03:47:44 */ @Test public void removeNode() { try { Document doc = reader.read(new File("file/catalog-modified.xml")); fail("comment: " + doc.selectSingleNode("//comment()")); //删除注释 doc.getRootElement().remove(doc.selectSingleNode("//comment()")); Element node = (Element) doc.selectSingleNode("//article"); //删除属性 node.remove(new DOMAttribute(QName.get("level"), "Introductory")); //删除元素 节点 node.remove(doc.selectSingleNode("//title")); //只能删除下一级节点,不能超过一级;(需要在父元素的节点上删除子元素) Node lastNameNode = node.selectSingleNode("//lastname"); lastNameNode.getParent().remove(lastNameNode); fail("Text: " + doc.selectObject("//*[text()='Ayesha']")); Element firstNameEl = (Element)doc.selectObject("//firstname"); fail("Text: " + firstNameEl.selectSingleNode("text()")); //删除text文本 //firstNameEl.remove(firstNameEl.selectSingleNode("text()")); //firstNameEl.remove(doc.selectSingleNode("//firstname/text()")); firstNameEl.remove(doc.selectSingleNode("//*[text()='Ayesha']/text()")); //删除子元素author //node.remove(node.selectSingleNode("//author")); fail(doc.asXML()); } catch (Exception e) { e.printStackTrace(); } } ~~~ 删除注释 <table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">doc.getRootElement().remove(doc.selectSingleNode("//comment()"));</span></p></td></tr></tbody></table> 删除root元素下面的注释 删除属性 <table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">node.remove(new DOMAttribute(QName.get("level"), "Introductory"));</span></p></td></tr></tbody></table> 删除node节点中的名称为level,其值为Introductory的属性 删除元素 <table border="1" cellpadding="0" cellspacing="0" height="32" width="401"><tbody><tr><td valign="top"><p><span style="font-size:13px">node.remove(doc.selectSingleNode("//title"));</span></p></td></tr></tbody></table> 删除node节点下的title元素 删除文本 <table border="1" cellpadding="0" cellspacing="0"><tbody><tr><td valign="top"><p><span style="font-size:13px">firstNameEl.remove(firstNameEl.selectSingleNode("text()"));</span></p><p><span style="font-size:13px">firstNameEl.remove(doc.selectSingleNode("//firstname/text()"));</span></p><p><span style="font-size:13px">firstNameEl.remove(doc.selectSingleNode("//*[text()='Ayesha']/text()"));</span></p></td></tr></tbody></table> 删除firstNameEl的文本内容
';

Jdom 操作XML

最后更新于:2022-04-01 14:22:32

可扩展标记语言——eXtensible MarkupLanguage 用户可以自己定义语言标记,只要有开始和闭合标签即可。 xsl装饰、修饰xml的显示结果。 dtd约束xml文件中的标记。 Ø XML的优点:     1、xml可以让数据和标记分离。     2、异质信息互通     3、机器语言     4、用交流语言替代html装饰语言     5、简单易用     6、可以自定义、可扩展   Ø XML和HTML比较 <table border="1" cellpadding="0" cellspacing="0" width="604"><tbody><tr><td valign="top" width="189"><p><span style="font-size:13px">比较内容</span></p></td><td valign="top" width="189"><p><span style="font-size:13px">HTML</span></p></td><td valign="top" width="224"><p><span style="font-size:13px">XML</span></p></td></tr><tr><td valign="top" width="189"><p><span style="font-size:13px">可扩展性</span></p></td><td valign="top" width="189"><p><span style="font-size:13px">不具有扩展性、标记固定</span></p></td><td valign="top" width="224"><p><span style="font-size:13px">是元标记语言,可以定义新标记,用户可以自定义标记</span></p></td></tr><tr><td valign="top" width="189"><p><span style="font-size:13px">侧重点</span></p></td><td valign="top" width="189"><p><span style="font-size:13px">侧重于信息的表现形式为什么格式被关注</span></p></td><td valign="top" width="224"><p><span style="font-size:13px">侧重于结构化的描述信息,数据是什么为XML所关注</span></p></td></tr><tr><td valign="top" width="189"><p><span style="font-size:13px">语法</span></p></td><td valign="top" width="189"><p><span style="font-size:13px">不严格(嵌套、配对)</span></p></td><td valign="top" width="224"><p><span style="font-size:13px">严格嵌套、配对,并按照DTD要求输出</span></p></td></tr><tr><td valign="top" width="189"><p><span style="font-size:13px">可读性、可维护性</span></p></td><td valign="top" width="189"><p><span style="font-size:13px">难于阅读和维护</span></p></td><td valign="top" width="224"><p><span style="font-size:13px">结构清晰,便于阅读维护</span></p></td></tr><tr><td valign="top" width="189"><p><span style="font-size:13px">数据本身、显示</span></p></td><td valign="top" width="189"><p><span style="font-size:13px">数据和显示合为一处</span></p></td><td valign="top" width="224"><p><span style="font-size:13px">数据与显示分离</span></p></td></tr><tr><td valign="top" width="189"><p><span style="font-size:13px">重用性</span></p></td><td valign="top" width="189"><p><span style="font-size:13px">低</span></p></td><td valign="top" width="224"><p><span style="font-size:13px">可重用性高</span></p></td></tr></tbody></table>   Ø **JDOM操作XML** JDOM可以很方便的操作XML文档,完成XML内容的创建、修改,已经遍历Document文档中的XML元素,完成查询等。下面我们就用JDOM完成这些功能。 # 准备 首先我们要准备jdom相关的jar包 jdom-jar下载地址:[http://www.jdom.org/dist/binary/](http://www.jdom.org/dist/binary/) jaxen在jdom的zip压缩包中可以找到。 Junit是测试用的,可以不添加。但需要用main方法测试。 Junit-jar[http://ebr.springsource.com/repository/app/bundle/version/download?name=com.springsource.org.junit&version=4.8.1&type=binary](http://ebr.springsource.com/repository/app/bundle/version/download?name=com.springsource.org.junit&version=4.8.1&type=binary)     其次,是准备测试工作。部分测试代码: ~~~ package com.hoo.test; import java.io.File; import java.io.IOException; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.jdom.Attribute; import org.jdom.Comment; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.Namespace; import org.jdom.Text; import org.jdom.input.SAXBuilder; import org.jdom.output.XMLOutputter; import org.jdom.xpath.XPath; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * <b>function:</b> JDOM操作XML * @author hoojo * @createDate 2011-8-4 下午12:34:09 * @file DocumentTest.java * @package com.hoo.test * @project JDOMTest * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class DocumentTest { private XMLOutputter out = null; @Before public void init() { //输出文件信息 out = new XMLOutputter(); } @After public void destory() { if (out != null) { out = null; } System.gc(); } /** * <b>function:</b>输出Document文档信息 * @author hoojo * @createDate 2011-8-5 下午12:10:27 * @param doc */ private void print(Document doc) { //设置XML文件编码格式 //out.setFormat(Format.getCompactFormat().setEncoding("gb2132")); System.out.println(out.outputString(doc)); } private void fail(Object o) { if (o != null) { System.out.println(o); } } } ~~~   # 创建Document ~~~ /** * 创建xml元素 */ @Test public void createDoc() { Document doc = null; //method 1、创建一个Doc文档,添加一个元素root doc = new Document(new Element("root")); print(doc); //method 2、创建一个Doc文档,添加一个元素root,设置root元素的节点文本 doc = new Document(new Element("root").setText("this is a root el")); print(doc); //method 3、创建一个Doc文档,添加一个元素root,设置root元素的节点文本且添加一个属性id,值为110 Element root = new Element("root"); root.setText("this is a root el"); root.setAttribute("id", "110"); doc.setRootElement(root); fail("method 3: \n" + out.outputString(doc)); //method 4、创建一个Doc文档,添加一个元素root,设置root元素的节点文本 doc = new Document(); doc.addContent(new Element("root").setText("this is a root el")); fail("method 4: \n" + out.outputString(doc)); fail(doc.toString()); } ~~~ * new Document可以创建一个doc文档 当给Document传递一个Element参数时,这个Element就是根元素; 当调用Document的setRootElement方法时,可以设置当前Doc的根元素; 当调用doc的addContent的时候,添加的元素将会是根元素; ~~~ doc = new Document(new Element("root").setText("this is a root el")); ~~~ 上面就创建了一个doc,根元素是root,root节点的内容是this is a root el; 注意setText方法返回的对象是当前Element,类似是StringBuffer的append方法;   * new Element()可以创建一个元素 如果传递参数那么这个参数将会是元素节点的名称; Element的setText方法可以设置元素的文本值; ~~~ Element root = new Element("root"); root.setText("this is a root el"); ~~~ 创建一个节点名称为root的元素,文本是this is a root el * setAttribute()可以设置某个具体节点的属性值 ~~~ root.setAttribute("id", "110"); ~~~ 给root节点添加一个id,值为110 * addContent添加注释 ~~~ root .addContent(new Comment("注释")); ~~~ 在root元素下添加一个注释; addContent是向元素中添加内容,而setContent是设置内容; * setText设置元素文本内容 ~~~ root.setText("this is a root el"); 同样 root. setContent(new Text("this is text")) 同样 root.addContent("this is text"); ~~~ 下面用上面的这些方法,创建一篇XML文档。文档内容如下: ~~~ /** 创建一遍xml文档 <?xml version="1.0" encoding="UTF-8"?> <car vin="123fhg5869705iop90"> <!--Description of a car--> <make>Toyota</make> <model>Celica</model> <year>1997</year> <color>green</color> <license state="CA">1ABC234</license> </car> */ @Test public void createXMLDoc() { //创建一个car的元素 Element carEl = new Element("car"); //创建vin属性,并设置值 carEl.setAttribute("vin", "123fhg5869705iop90"); //创建注释 carEl.addContent(new Comment("Description of a car")); //创建一个make元素,设置文本内容 carEl.addContent(new Element("make").setText("Toyota")); //创建一个model元素,添加一个文本元素 carEl.addContent(new Element("model").setContent(new Text("Celica"))); //创建一个year元素,添加文本内容 carEl.addContent(new Element("year").addContent("1997")); //创建一个color元素,文本内容是green carEl.addContent(new Element("color").setText("green")); //创建一个license的元素 Element licenseEl = new Element("license"); //为license元素添加文本内容 licenseEl.addContent("1ABC234"); //创建一个state的属性,值为CA licenseEl.setAttribute("state", "CA"); //将licenseEl添加到根元素中 carEl.addContent(licenseEl); //将car元素设置为根元素 Document doc = new Document(carEl); print(doc); /*out = new XMLOutputter(); try { out.output(doc, System.out); } catch (IOException e) { e.printStackTrace(); }*/ } ~~~ 方法运行后,所创建的文档和上面注释文档内容相同   # 读取XML文件的内容 disk.xml文件内容如下: ~~~ <?xml version="1.0" encoding="UTF-8"?> <HD> <disk name="C"> <capacity>8G</capacity> <directories>200</directories> <files>1580</files> </disk> <disk name="D"> <capacity>10G</capacity> <directories>500</directories> <files>3000</files> </disk> <disk2 name="E"> <capacity>11G</capacity> <directories>50</directories> <files size="200" modifyDate="2011-08-3"> <file>Java book</file> <file>Spring.txt</file> <file>strtus.doc</file> </files> </disk2> <files size="220">500</files> </HD> ~~~ 读取disk文件的内容,代码如下: ~~~ /** * <b>function:</b>读取xml文件中的元素 * @author hoojo * @createDate 2011-8-4 下午04:54:17 */ @Test @SuppressWarnings("unchecked") public void readXMLContent() { SAXBuilder builder = new SAXBuilder(); try { Document doc = builder.build(new File("file/disk.xml")); Element rootEl = doc.getRootElement(); //获得所有子元素 List<Element> list = rootEl.getChildren(); //List<Element> list = rootEl.getChildren("disk"); for (Element el : list) { //获取name属性值 String name = el.getAttributeValue("name"); //获取子元素capacity文本值 String capacity = el.getChildText("capacity"); //获取子元素directories文本值 String directories = el.getChildText("directories"); String files = el.getChildText("files"); System.out.println("磁盘信息:"); System.out.println("分区盘符:" + name); System.out.println("分区容量:" + capacity); System.out.println("目录数:" + directories); System.out.println("文件数:" + files); System.out.println("-----------------------------------"); } } catch (JDOMException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } ~~~ * getChildren方法可以获取所有子元素 * getChildren(elName)可以获取所有名称为elName的子节点 * getAttributeValue可以获取指定属性的值 * getChildText可以获取子节点的文本值   # 递归显示文档信息 ~~~ /** * 递归返回指定格式的“--” */ private String format(int i) { String temp = ""; if (i > 0) { temp += "--"; i--; temp += format(i); } return temp; } /** * <b>function:</b>显示当前节点所有Element的属性信息 * @author hoojo * @createDate 2011-8-4 下午06:10:53 * @param el * @return */ @SuppressWarnings("unchecked") private String getAttrInfo(Element el) { List<Attribute> attrs = el.getAttributes(); return getAttrInfo(attrs); } /** * <b>function:</b>显示属性信息 * @author hoojo * @createDate 2011-8-9 下午03:52:59 * @param attrs * @return */ private String getAttrInfo(List<Attribute> attrs) { StringBuilder info = new StringBuilder(); for (Attribute attr : attrs) { info.append(attr.getName()).append("=").append(attr.getValue()).append(", "); } if (info.length() > 0) { return "[" + info.substring(0, info.length() - 2)+ "]"; } return ""; } /** * <b>function:</b>递归显示文档节点元素信息 * @author hoojo * @createDate 2011-8-4 下午05:56:34 * @param i * @param list */ @SuppressWarnings("unchecked") private void print(int i, List<Element> list) { i++; for (Element el : list) { List<Element> childs = el.getChildren(); if (childs.size() > 0) { fail(format(i) + el.getName() + " " + getAttrInfo(el)); print(i, childs); } else { fail(format(i) + el.getName() + ":" + el.getText() + " " + getAttrInfo(el)); } } } ~~~ 调用print(0, root.getChildren());方法就可以看到一篇格式化后输出的文档内容 ~~~ #############显示文档信息############### --HD ----disk [name=C] ------capacity:8G ------directories:200 ------files:1580 ----disk [name=D] ------capacity:10G ------directories:500 ------files:3000 ----disk2 [name=E] ------capacity:11G ------directories:50 ------files [size=200, modifyDate=2011-08-3] --------file:Java book --------file:Spring.txt --------file:strtus.doc ----files:500 [size=220] ~~~   # XPath查询遍历XML文档 ~~~ /** * <b>function:</b>用xpath遍历xml信息 * @author hoojo * @createDate 2011-8-4 下午04:56:52 * xpath参考:http://www.w3school.com.cn/xpath/xpath_functions.asp * * nodeName 选取此节点的所有子节点 / 从根节点选取 // 从匹配选择的当前节点选择文档中的节点,而不考虑它们的 . 选取当前节点 .. 选取当前节点的父节点 @ 选取属性 * 匹配任何元素节点 @* 匹配任何属性节点 node() 配任何类型的节点 ancestor 选取当前节点的所有先辈(父、祖父等) ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身 attribute 选取当前节点的所有属性 child 选取当前节点的所有子元素。 descendant 选取当前节点的所有后代元素(子、孙等)。 descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 following 选取文档中当前节点的结束标签之后的所有节点。 namespace 选取当前节点的所有命名空间节点 parent 选取当前节点的父节点。 preceding 选取文档中当前节点的开始标签之前的所有节点。 preceding-sibling 选取当前节点之前的所有同级节点。 self 选取当前节点。 child::book 选取所有属于当前节点的子元素的 book 节点 attribute::languane 选取当前节点的 languange 属性 child::* 选取当前节点的所有子元素 attribute::* 选取当前节点的所有属性 child::text() 选取当前节点的所有文本子节点 child::node() 选取当前节点的所有子节点 descendant::book 选取当前节点的所有 book 后代 ancestor::book 选择当前节点的所有 book 先辈 */ @SuppressWarnings("unchecked") @Test public void queryElementByXPath() { SAXBuilder builder = new SAXBuilder(); try { Document doc = builder.build(new File("file/disk.xml")); List<Element> list = XPath.selectNodes(doc, "/HD/disk"); for (Element el : list) { String name = el.getAttributeValue("name"); String capacity = el.getChildText("capacity"); String directories = el.getChildText("directories"); String files = el.getChildText("files"); System.out.println("磁盘信息:"); System.out.println("分区盘符:" + name); System.out.println("分区容量:" + capacity); System.out.println("目录数:" + directories); System.out.print("文件数:" + files); String capacityText = ((Text) XPath.selectSingleNode(el, "//disk[@name='" + name + "']/capacity/text()")).getTextNormalize(); System.out.println("#" + capacityText); System.out.println("-----------------------------------"); } //显示文档信息 System.out.println("#############显示文档信息###############"); print(0, doc.getContent()); //获得hd元素 System.out.println("#############显示HD子元素信息###############"); Element root = (Element) XPath.selectSingleNode(doc, "/HD"); //fail(root.getChildren().size()); print(0, root.getChildren()); //获取hd下所有元素 System.out.println("#############显示HD子元素信息###############"); List roots = (List) XPath.selectNodes(doc, "/HD/*"); //fail(roots.size()); print(0, roots); //获得hd下的所有disk元素 System.out.println("#############显示disk信息###############"); roots = (List) XPath.selectNodes(doc, "/HD/disk"); //fail(roots.size()); print(0, roots); System.out.println("#############显示disk2信息###############"); roots = (List) XPath.selectNodes(doc, "/HD/disk2"); print(0, roots); System.out.println("#############显示任意路径下的files信息###############"); roots = (List) XPath.selectNodes(doc, "//files"); print(0, roots); System.out.println("#############显示任意路径下的files指定下标的file信息###############"); roots = (List) XPath.selectNodes(doc, "//files/file[1]"); print(0, roots); System.out.println("#############显示任意路径下的files最后的file信息###############"); roots = (List) XPath.selectNodes(doc, "//files/file[last()]"); print(0, roots); System.out.println("#############显示任意路径下的files倒数第二的file信息###############"); roots = (List) XPath.selectNodes(doc, "//files/file[last() - 1]"); print(0, roots); System.out.println("#############显示任意路径下的files的子元素file位置position在第二的file信息###############"); roots = (List) XPath.selectNodes(doc, "//files/file[position() = 2]"); //roots = (List) XPath.selectNodes(doc, "//files/file[position() > 2]"); print(0, roots); System.out.println("#############显示任意路径下的files第三个file的当前节点的前面所有同级节点信息###############"); roots = (List) XPath.selectNodes(doc, "//files/file[3]/preceding-sibling::*"); print(0, roots); System.out.println("#############显示任意路径下的disk2之前的所有节点信息###############"); roots = (List) XPath.selectNodes(doc, "//disk2/preceding::*"); print(0, roots); System.out.println("#############显示任意路径下的disk2之后的所有节点信息###############"); roots = (List) XPath.selectNodes(doc, "//disk2/following::*"); print(0, roots); System.out.println("#############显示任意路径下的files的所有属性信息###############"); roots = (List) XPath.selectNodes(doc, "//files/attribute::*"); fail(getAttrInfo(roots)); System.out.println("#############显示任意路径下的节点是disk属性name=C的信息###############"); roots = (List) XPath.selectNodes(doc, "//disk[@name='C']"); print(0, roots); System.out.println("#############显示任意路径下的节点是disk的子元素的文本中含义5和8节点的信息###############"); roots = (List) XPath.selectNodes(doc, "//disk/child::*[contains(text(), '8') and contains(text(), '5')]"); //roots = (List) XPath.selectNodes(doc, "//disk/child::*[contains(text(), '8') or contains(text(), '5')]"); print(0, roots); System.out.println("#############显示任意路径下的节点是files且有属性size的信息###############"); roots = (List) XPath.selectNodes(doc, "//files[@size]"); print(0, roots); System.out.println("#############显示HD节点下capacity的值为11G的信息###############"); //roots = (List) XPath.selectNodes(doc, "/HD/disk/capacity[text()='11G']"); roots = (List) XPath.selectNodes(doc, "/HD/*/capacity[text()='11G']"); //roots = (List) XPath.selectNodes(doc, "/*/*/capacity[text()='11G']"); print(0, roots); //parent::*表示父节点集合 System.out.println("#############显示任意路径下的节点是files且属性size有值的父节点的信息###############"); roots = (List) XPath.selectNodes(doc, "//files[@size='200']/parent::*"); print(0, roots); System.out.println("#############显示任意路径下的节点disk的子节点的capacity信息###############"); roots = (List) XPath.selectNodes(doc, "//disk/child::capacity"); print(0, roots); //获取c盘的大小 System.out.println("获取c盘的大小"); Text filesText = (Text) XPath.selectSingleNode(doc, "/HD/disk[@name='C']/files/text()"); System.out.println(filesText.getTextNormalize()); //XPath function /** string concat (string, string, string*) 联接两个字符串 boolean starts-with (string, string) 判断某字符串是否以另一字符串开头 boolean contains (string, string) 判断某字符串是否包含另一字符串 string substring (string, number, number) 取子字符串 number string-length (string) 测字符串长度 number sum (node-set) 求和 number floor (number) 求小于此数的最大整数值 number ceiling (number) 求大于此数最小整数值 **/ System.out.println("获取@size的和大于200的"); roots = (List) XPath.selectNodes(doc, "//files[sum(@size) > 200]"); print(0, roots); System.out.println("查找directories的内容长度小于3的"); roots = (List) XPath.selectNodes(doc, "//directories[string-length(text()) < 3]"); print(0, roots); System.out.println("查找files的内容包含5的"); roots = (List) XPath.selectNodes(doc, "//files[contains(text(), '5')]"); print(0, roots); } catch (JDOMException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } ~~~   # 删除元素及其他操作 ~~~ /** * <b>function:</b>打印doc相关信息 * @author hoojo * @createDate 2011-8-10 下午06:29:01 */ @SuppressWarnings("unchecked") @Test public void printInfo() { SAXBuilder builder = new SAXBuilder(); try { //builder.setFeature("user", true); //builder.setIgnoringBoundaryWhitespace(true); //忽略元素内容的空格 //builder.setIgnoringElementContentWhitespace(true); Document doc = builder.build(new File("file/web.xml")); fail("baseURI: " + doc.getBaseURI()); fail("ContentSize: " + doc.getContentSize()); //System.out.println("getContent: "); //print(0, doc.getContent()); fail("getContent index: " + doc.getRootElement().getContent(1)); fail("getDocType: " + doc.getDocType()); fail("getParent: " + doc.getRootElement().getContent(1).getParent()); fail("getProperty: " + doc.getProperty("filter")); print(0, XPath.selectNodes(doc, "//*[contains(text(), '#')]")); fail("getText: " + ((Element)XPath.selectNodes(doc, "//*[contains(text(), '#')]").get(0)).getText()); fail("getTextTrim: " + ((Element)XPath.selectNodes(doc, "//*[contains(text(), '#')]").get(0)).getTextTrim()); fail("getTextNormalize: " + ((Element)XPath.selectNodes(doc, "//*[contains(text(), '#')]").get(0)).getTextNormalize()); fail("hasRootElement: " + doc.hasRootElement()); //如果文档带有Namespace一定要设置Namespace,不然无法读取内容 Namespace ns = Namespace.getNamespace("http://java.sun.com/xml/ns/javaee"); Element servletEl = doc.getRootElement().getChild("servlet", ns); fail("servletEl: " + servletEl); print(0, servletEl.getChildren()); fail("getChildText: " + servletEl.getChildText("servlet-class", ns)); fail("getChildTextNormalize: " + servletEl.getChildTextNormalize("servlet-name", ns)); fail("getChildTextTrim: " + servletEl.getChildTextTrim("servlet-class", ns)); fail("getName: " + servletEl.getName()); fail("getNamespacePrefix: " + servletEl.getNamespacePrefix()); fail("getNamespace: " + servletEl.getNamespace()); fail("getQualifiedName: " + servletEl.getQualifiedName()); Element classEl = servletEl.getChild("servlet-class", ns); fail("getText: " + classEl.getText()); fail("getTextNormalize: " + classEl.getTextNormalize()); fail("getTextTrim: " + classEl.getTextTrim()); fail("getValue: " + classEl.getValue()); //删除节点 fail(doc.getRootElement().removeContent(3)); //print(0, doc.removeContent()); //print(0, doc.getRootElement().getChildren()); fail(servletEl.removeChild("servlet-class", ns)); fail(servletEl.removeChildren("init-param", ns)); print(0, servletEl.getChildren()); } catch (JDOMException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } ~~~
';

SpringMVC 中整合JSON、XML视图一

最后更新于:2022-04-01 14:22:30

SpringMVC中整合了JSON、XML的视图,可以通过这些视图完成Java对象到XML、JSON的转换。转换XML提供了MarshallingView,开发者只需用注入相应的marshaller、和属性配置,即可自动完成Java的Model对象中的数据到XML的编组。 Email:hoojo_@126.com Blog:[http://blog.csdn.net/IBM_hoojo](http://blog.csdn.net/IBM_hoojo) [http://hoojo.cnblogs.com/](http://hoojo.cnblogs.com/) ### 一、准备工作 1、 本次程序会涉及到Jackson、xStream、Jibx、Jaxb2、castor等技术,如果你对这些技术还不是很了解。建议阅读:[http://www.cnblogs.com/hoojo/archive/2011/04/27/2030264.html](http://www.cnblogs.com/hoojo/archive/2011/04/27/2030264.html) 这篇文章中涉及到的内容应该对你有不少帮助。 2、 jar包下载 spring各版本jar下载地址:[http://ebr.springsource.com/repository/app/library/detail?name=org.springframework.spring](http://ebr.springsource.com/repository/app/library/detail?name=org.springframework.spring) 相关的依赖包也可以在这里找到:[http://ebr.springsource.com/repository/app/library](http://ebr.springsource.com/repository/app/library) 3、 至少需要以下jar包 [![clip_image002](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-15_57105c492db5e.gif "clip_image002")](http://hi.csdn.net/attachment/201104/29/0_1304048530oJvk.gif) 4、 当前工程的web.xml配置 ~~~ <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <-- 配置Spring核心控制器 --> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/dispatcher.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <-- 解决工程编码过滤器 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app> ~~~ 5、 WEB-INF中的dispatcher.xml配置 ~~~ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"> <-- 注解探测器 --> <context:component-scan base-package="com.hoo.controller"/> <-- 视图解析器,根据视图的名称new ModelAndView(name),在配置文件查找对应的bean配置 --> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"> <property name="order" value="1"/> </bean> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> </bean> </beans> ~~~ 启动后,可以看到index.jsp 没有出现异常或错误。那么当前SpringMVC的配置就成功了。 ### 二、利用Jaxb2编组XML 1、 Jaxb2可以完成XML和Java的相互转换,在WebService中用得较多。前面也介绍过Jaxb2 的用法。 在线博文: For cnblogs:[http://www.cnblogs.com/hoojo/archive/2011/04/26/2029011.html](http://www.cnblogs.com/hoojo/archive/2011/04/26/2029011.html) For csdn:[http://blog.csdn.net/IBM_hoojo/archive/2011/04/26/6363491.aspx](http://blog.csdn.net/IBM_hoojo/archive/2011/04/26/6363491.aspx) 2、 首先在dispatcher.xml中配置Jaxb2的marshaller的视图,配置如下: ~~~ <-- xml视图,Jaxb2Marshaller,需要配置对象和对象添加Annotation xml注解,不需要添加额外的jar包 --> <bean name="jaxb2MarshallingView" class="org.springframework.web.servlet.view.xml.MarshallingView"> <constructor-arg> <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <array> <value>com.hoo.entity.User</value> <value>com.hoo.entity.AccountBean</value> <value>com.hoo.entity.MapBean</value> <value>com.hoo.entity.ListBean</value> </array> </property> </bean> </constructor-arg> </bean> ~~~ Jaxb2的jar在jdk中已经包含,所以不需要添加额外的jar包。详细信息你可以参考1中的博文。上面的jaxb2MarshallingView视图的class是MarshallingView,它有一个构造器需要传递一个Marshaller。Marshaller主要完成编组,即将Java对象转换成XML的这么一个东东。我们在这个构造器中注入了Jaxb2Marshaller这个类,这个bean有一个classesToBeBound属性,这个属性是一个数组。需要将即将转换成XML的Java对象配置在这里。而且这些对象需要进行Annotation注解。 3、 创建Jaxb2MarshallingViewController,完成Java对象到XML的转换 单个JavaBean的转换,代码如下: ~~~ package com.hoo.controller; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.hoo.entity.AccountBean; import com.hoo.entity.Brithday; import com.hoo.entity.DifferBean; import com.hoo.entity.ListBean; import com.hoo.entity.MoreBean; import com.hoo.entity.User; /** * function:Jaxb2MarshallingView 视图,利用Jaxb2进行Java对象到XML的转换技术 * @author hoojo * @createDate 2011-4-27 下午03:20:23 * @file Jaxb2MarshallingViewController.java * @package com.hoo.controller * @project SpringMVC4View * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ @Controller @RequestMapping("/jaxb2/view") public class Jaxb2MarshallingViewController { /* * MarshallingView Jaxb2Marshaller 需要配置转换成xml的java对象的Annotation */ @RequestMapping("/doXMLJaxb2") public ModelAndView doXMLJaxb2View() { System.out.println("#################ViewController doXMLJaxb2View##################"); ModelAndView mav = new ModelAndView("jaxb2MarshallingView"); AccountBean bean = new AccountBean(); bean.setAddress("address"); bean.setEmail("email"); bean.setId(1); bean.setName("haha"); Brithday day = new Brithday(); day.setBrithday("2010-11-22"); bean.setBrithday(day); mav.addObject(bean); return mav; } } ~~~ 上面的代码的ModelAndView配置了jaxb2MarshallingView这个视图,就表示结果集会通过这个视图进行编组后显示。上面需要转换的AccountBean和Birthday对象,这些对象需要配置annotation,[前面已经讲到annotation对JavaBean转换XML的作用](http://www.cnblogs.com/hoojo/archive/2011/04/26/2029011.html)。我们来看看AccountBean对象代码: ~~~ package com.hoo.entity; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "account") public class AccountBean { private int id; private String name; private String email; private String address; private Brithday brithday; @XmlElement public Brithday getBrithday() { return brithday; } public void setBrithday(Brithday brithday) { this.brithday = brithday; } @XmlElement public int getId() { return id; } public void setId(int id) { this.id = id; } @XmlElement public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElement public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return this.name + "#" + this.id + "#" + this.address + "#" + this.brithday + "#" + this.email; } } ~~~ 在getter方法都有部分注解,如果你想了解更多的jaxb2的相关技术,参考:[http://www.cnblogs.com/hoojo/archive/2011/04/26/2029011.html](http://www.cnblogs.com/hoojo/archive/2011/04/26/2029011.html) Brithday ~~~ package com.hoo.entity; public class Brithday { private String brithday; public Brithday() {} public Brithday(String brithday) { this.brithday = brithday; } public String getBrithday() { return brithday; } public void setBrithday(String brithday) { this.brithday = brithday; } } ~~~ Brithday是AccountBean中的一个属性,在AccountBean中已经注解过。这里就不需要进行注解配置。 通过浏览器请求:[http://localhost:8080/SpringMVC4View/jaxb2/view/doXMLJaxb2.do](http://localhost:8080/SpringMVC4View/jaxb2/view/doXMLJaxb2.do) 结果如下: ~~~ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <account><address>address</address><brithday><brithday>2010-11-22</brithday></brithday> <email>email</email><id>1</id><name>haha</name></account> ~~~ 4、 转换带List属性的JavaEntity ~~~ /** * function:转换带有List属性的JavaBean * @author hoojo * @createDate 2011-4-27 下午05:32:22 * @return */ @RequestMapping("/doListXMLJaxb2") public ModelAndView doListXMLJaxb2View() { System.out.println("#################ViewController doListXMLJaxb2View##################"); ModelAndView mav = new ModelAndView("jaxb2MarshallingView"); List<Object> beans = new ArrayList<Object>(); for (int i = 0; i < 3; i++) { AccountBean bean = new AccountBean(); bean.setAddress("address#" + i); bean.setEmail("email" + i + "@12" + i + ".com"); bean.setId(1 + i); bean.setName("haha#" + i); Brithday day = new Brithday(); day.setBrithday("2010-11-2" + i); bean.setBrithday(day); beans.add(bean); User user = new User(); user.setAddress("china GuangZhou# " + i); user.setAge(23 + i); user.setBrithday(new Date()); user.setName("jack#" + i); user.setSex(Boolean.parseBoolean(i + "")); beans.add(user); } ListBean list = new ListBean(); list.setList(beans); mav.addObject(list); return mav; } ~~~ ListBean注解过的代码 ~~~ package com.hoo.entity; import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlRootElement; @SuppressWarnings("unchecked") @XmlRootElement public class ListBean { private String name; private List list; @XmlElements({ @XmlElement(name = "user", type = User.class), @XmlElement(name = "account", type = AccountBean.class), }) public List getList() { return list; } public void setList(List list) { this.list = list; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ~~~ 通过上面的注解可以看出List中只能存储User、AccountBean对象,关于User对象的代码和AccountBean对象的是一样的,只是类名不同而已。读者可以自己添加。在WebBrowser中请求:[http://localhost:8080/SpringMVC4View/jaxb2/view/doListXMLJaxb2.do](http://localhost:8080/SpringMVC4View/jaxb2/view/doListXMLJaxb2.do) 结果如下: ~~~ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <listBean> <account><address>address#0</address><brithday><brithday>2010-11-20</brithday></brithday> <email>email0@120.com</email><id>1</id><name>haha#0</name></account> <user><address>china GuangZhou# 0</address><age>23</age> <brithday>2011-04-27T17:02:38.028+08:00</brithday><name>jack#0</name><sex>false</sex></user> <account><address>address#1</address><brithday><brithday>2010-11-21</brithday></brithday> <email>email1@121.com</email><id>2</id><name>haha#1</name></account> <user><address>china GuangZhou# 1</address><age>24</age> <brithday>2011-04-27T17:02:38.028+08:00</brithday><name>jack#1</name><sex>false</sex></user> <account><address>address#2</address><brithday><brithday>2010-11-22</brithday></brithday> <email>email2@122.com</email><id>3</id><name>haha#2</name></account> <user><address>china GuangZhou# 2</address><age>25</age> <brithday>2011-04-27T17:02:38.028+08:00</brithday><name>jack#2</name><sex>false</sex></user> </listBean> ~~~ 5、 转换带有Map属性的JavaBean,Jaxb2转换Map有点复杂,先看看代码: ~~~ /** * function:转换带有Map属性的JavaBean * @author hoojo * @createDate 2011-4-27 下午05:32:42 * @return */ @RequestMapping("/doMapXMLJaxb2") public ModelAndView doMapXMLJaxb2View() { System.out.println("#################ViewController doMapXMLJaxb2View##################"); ModelAndView mav = new ModelAndView("jaxb2MarshallingView"); MapBean mapBean = new MapBean(); HashMap map = new HashMap(); AccountBean bean = new AccountBean(); bean.setAddress("北京"); bean.setEmail("email"); bean.setId(1); bean.setName("jack"); Brithday day = new Brithday(); day.setBrithday("2010-11-22"); bean.setBrithday(day); map.put("NO1", bean); bean = new AccountBean(); bean.setAddress("china"); bean.setEmail("tom@125.com"); bean.setId(2); bean.setName("tom"); day = new Brithday("2011-11-22"); bean.setBrithday(day); map.put("NO2", bean); mapBean.setMap(map); mav.addObject(mapBean); return mav; } ~~~ 首先看看MapBean的代码,代码很简单就一个Map的属性。 ~~~ package com.hoo.entity; import java.util.HashMap; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import com.hoo.util.MapAdapter; @XmlRootElement public class MapBean { private HashMap map; @XmlJavaTypeAdapter(MapAdapter.class) public HashMap getMap() { return map; } public void setMap(HashMap map) { this.map = map; } } ~~~ 上面的代码的getMap方法设置了XmlJavaTypeAdapter这个注解,注解里面的MapAdapter是我们自己实现的,而且还要构建一个MapElements数组元素。主要是继承XmlAdapter重写里面的几个方法完成的。 MapAdapter代码 ~~~ package com.hoo.util; import java.util.HashMap; import java.util.Map; import javax.xml.bind.annotation.adapters.XmlAdapter; import com.hoo.entity.AccountBean; /** * function:AccountBean 编组、解组的XmlAdapter * @author hoojo * @createDate 2011-4-25 下午05:03:18 * @file MyAdetper.java * @package com.hoo.util * @project WebHttpUtils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class MapAdapter extends XmlAdapter> { public MapElements[] marshal(Map arg0) throws Exception { MapElements[] mapElements = new MapElements[arg0.size()]; int i = 0; for (Map.Entry entry : arg0.entrySet()) mapElements[i++] = new MapElements(entry.getKey(), entry.getValue()); return mapElements; } public Map unmarshal(MapElements[] arg0) throws Exception { Map r = new HashMap(); for (MapElements mapelement : arg0) r.put(mapelement.key, mapelement.value); return r; } } ~~~ MapElements代码 ~~~ package com.hoo.util; import javax.xml.bind.annotation.XmlElement; import com.hoo.entity.AccountBean; /** * function: MapElements * @author hoojo * @createDate 2011-4-25 下午05:04:04 * @file MyElements.java * @package com.hoo.util * @project WebHttpUtils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class MapElements { @XmlElement public String key; @XmlElement public AccountBean value; @SuppressWarnings("unused") private MapElements() { } // Required by JAXB public MapElements(String key, AccountBean value) { this.key = key; this.value = value; } } ~~~ 在浏览器中请求:[http://localhost:8080/SpringMVC4View/jaxb2/view/doMapXMLJaxb2.do](http://localhost:8080/SpringMVC4View/jaxb2/view/doMapXMLJaxb2.do) 结果如下: ~~~ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <mapBean><map><item><key>NO2</key><value><address>china</address> <brithday><brithday>2011-11-22</brithday></brithday> <email>tom@125.com</email><id>2</id><name>tom</name></value></item> <item><key>NO1</key><value><address>北京</address><brithday><brithday>2010-11-22</brithday></brithday> <email>email</email><id>1</id><name>jack</name></value></item></map> </mapBean> ~~~ 总结,如果你想将一些Java的基本类型转换成XML。那么你得创建一个带getter、setter方法的JavaBean。然后在Bean的getter方法进行相应的Annotation注解即可完成转换。 ### 三、利用xStream转换XML 1、 xStream可以轻易的将Java对象转换成XML、JSON,Spring整合利用xStream转换xml。需要添加xStream相关的xstream-1.3.1.jar包。 如果你对xStream不上很了解,你可以先阅读这篇文章: For csblogs:[http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html) For csdn:[http://blog.csdn.net/IBM_hoojo/archive/2011/04/22/6342386.aspx](http://blog.csdn.net/IBM_hoojo/archive/2011/04/22/6342386.aspx) 2、 然后在dispatcher.xml中添加如下配置 ~~~ <-- xml视图,XStreamMarshaller,可以转换任何形式的java对象,需要添加xStream jar包 --> <bean name="xStreamMarshallingView" class="org.springframework.web.servlet.view.xml.MarshallingView"> <property name="marshaller"> <bean class="org.springframework.oxm.xstream.XStreamMarshaller"> <-- 启用annotation --> <property name="autodetectAnnotations" value="true"/> <-- 类名别名 --> <property name="aliases"> <map> <-- Account这个类的别名就变成了myBeans,那么转换后的xml中就是myBeans --> <entry key="myBeans" value="com.hoo.entity.Account"/> </map> </property> <-- 基本属性别名 --> <property name="fieldAliases"> <map> <-- Account中的brithday这个属性 --> <entry key="com.hoo.entity.Account.brithday" value="生日"/> </map> </property> </bean> </property> </bean> ~~~ 上次配置的参数有注释描述,还要没有配置的参数。如:annotatedClass、annotatedClasses是当没有配置启用annotation的时候,可以用这2个属性进行配置你指定的class启用annotation注解。streamDriver是配置驱动用的,默认可以不要驱动,你可以配置DomDriver、JSON相关的驱动。encoding是设置编码,关于XStreamMarshaller还要更多的参数配置和上面xStream 的博文中讲解的一样使用,只是通过配置,而博文中是直接在代码中写的。当然也可以通过annotation进行注解哦;如果你想了解更多xStream的用法,请你仔细阅读:[http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html) 3、 普通JavaBean转换XML ~~~ package com.hoo.controller; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.hoo.entity.Account; import com.hoo.entity.AccountArray; import com.hoo.entity.AccountBean; import com.hoo.entity.Brithday; import com.hoo.entity.DifferBean; import com.hoo.entity.ListBean; import com.hoo.entity.MapBean; import com.hoo.entity.MoreBean; import com.hoo.entity.User; /** * function:Jaxb2MarshallingView 视图,利用Jaxb2进行Java对象到XML的转换技术 * @author hoojo * @createDate 2011-4-27 下午03:20:23 * @file Jaxb2MarshallingViewController.java * @package com.hoo.controller * @project SpringMVC4View * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ @Controller @RequestMapping("/jaxb2/view") public class Jaxb2MarshallingViewController { /* * MarshallingView Jaxb2Marshaller 需要配置转换成xml的java对象的Annotation */ @RequestMapping("/doXMLJaxb2") public ModelAndView doXMLJaxb2View() { System.out.println("#################ViewController doXMLJaxb2View##################"); ModelAndView mav = new ModelAndView("jaxb2MarshallingView"); AccountBean bean = new AccountBean(); bean.setAddress("address"); bean.setEmail("email"); bean.setId(1); bean.setName("haha"); Brithday day = new Brithday(); day.setBrithday("2010-11-22"); bean.setBrithday(day); mav.addObject(bean); return mav; } } ~~~ AccountBean上面的代码已经给出,这里就不重复了。值得说明的是xStream在ModelAndView中,直接用addObject方法添加时,有时候出现一些不是我们转换的对象的信息,一般是BindingResult的xml信息。解决办法就是设置addObject的key。Key设置为BindingResult.*MODEL_KEY_PREFIX*这样就可以了,代码上面已经给出。 在浏览器中请求:[http://localhost:8080/SpringMVC4View/xStream/view/doXMLXStream.do](http://localhost:8080/SpringMVC4View/xStream/view/doXMLXStream.do) 结果如下: ~~~ <com.hoo.entity.AccountBean><id>1</id><name>haha</name><email>email</email><address>北京</address> <brithday><brithday>2010-11-22</brithday></brithday></com.hoo.entity.AccountBean> ~~~ 4、 转换对象数组 代码如下: ~~~ /** * function:转换对象数组 * @author hoojo * @createDate 2011-4-27 下午06:19:40 * @return */ @RequestMapping("/doMoreXMLXStream") public ModelAndView doMoreXMLXStreamView() { System.out.println("#################ViewController doMoreXMLXStreamView##################"); ModelAndView mav = new ModelAndView("xStreamMarshallingView"); Account[] accs = new Account[2]; Account bean = new Account(); bean.setAddress("北京"); bean.setEmail("email"); bean.setId(1); bean.setName("haha"); Brithday day = new Brithday(); day.setBrithday("2010-11-22"); bean.setBrithday(day); accs[0] = bean; bean = new Account(); bean.setAddress("上海"); bean.setEmail("email"); bean.setId(1); bean.setName("haha"); day = new Brithday(); day.setBrithday("2010-11-22"); bean.setBrithday(day); accs[1] = bean; mav.addObject(accs); return mav; } ~~~ 在WebBrowser中请求[http://localhost:8080/SpringMVC4View/xStream/view/doMoreXMLXStream.do](http://localhost:8080/SpringMVC4View/xStream/view/doMoreXMLXStream.do) 结果如下: ~~~ <myBeans-array><myBeans><id>1</id><name>haha</name><email>email</email> <address>北京</address><生日><brithday>2010-11-22</brithday></生日></myBeans> <myBeans><id>1</id><name>haha</name><email>email</email><address>上海</address> <生日><brithday>2010-11-22</brithday></生日></myBeans></myBeans-array> ~~~ 结果中的myBeans、生日就是在dispatcher配置文件中重命名的对象属性名称。 5、 转换Map集合 ~~~ /** * function:转换Map对象 * @author hoojo * @createDate 2011-4-27 下午06:19:48 * @return */ @RequestMapping("/doDifferXMLXStream") public ModelAndView doDifferXMLXStreamView() { System.out.println("#################ViewController doDifferXMLXStreamView##################"); ModelAndView mav = new ModelAndView("xStreamMarshallingView"); Account bean = new Account(); bean.setAddress("广东"); bean.setEmail("email"); bean.setId(1); bean.setName("haha"); Brithday day = new Brithday(); day.setBrithday("2010-11-22"); bean.setBrithday(day); User user = new User(); user.setAddress("china GuangZhou"); user.setAge(23); user.setBrithday(new Date()); user.setName("jack"); user.setSex(true); Map map = new HashMap(); map.put("bean", bean); map.put("user", user); mav.addObject(map); return mav; } ~~~ 在WebBrowser中请求[http://localhost:8080/SpringMVC4View/xStream/view/doDifferXMLXStream.do](http://localhost:8080/SpringMVC4View/xStream/view/doDifferXMLXStream.do) 结果如下: ~~~ <map><entry> <string>bean</string><myBeans><id>1</id><name>haha</name><email>email</email> <address>广东</address><生日><brithday>2010-11-22</brithday></生日></myBeans> </entry><entry><string>user</string><com.hoo.entity.User><name>jack</name><age>23</age><sex>true</sex> <address>china GuangZhou</address><brithday>2011-04-27 19:02:13.747 CST</brithday></com.hoo.entity.User> </entry></map> ~~~ 6、 转换List集合 ~~~ /** * function:转换List对象 * @author hoojo * @createDate 2011-4-27 下午06:20:02 * @return */ @RequestMapping("/doListXMLXStream") public ModelAndView doListXMLXStreamView() { System.out.println("#################ViewController doListXMLXStreamView##################"); ModelAndView mav = new ModelAndView("xStreamMarshallingView"); List<Object> beans = new ArrayList<Object>(); for (int i = 0; i < 3; i++) { Account bean = new Account(); bean.setAddress("北京#" + i); bean.setEmail("email" + i + "@12" + i + ".com"); bean.setId(1 + i); bean.setName("haha#" + i); Brithday day = new Brithday(); day.setBrithday("2010-11-2" + i); bean.setBrithday(day); beans.add(bean); User user = new User(); user.setAddress("china GuangZhou 广州# " + i); user.setAge(23 + i); user.setBrithday(new Date()); user.setName("jack#" + i); user.setSex(Boolean.parseBoolean(i + "")); beans.add(user); } mav.addObject(beans); return mav; } ~~~ 在WebBrowser中请求[http://localhost:8080/SpringMVC4View/xStream/view/doListXMLXStream.do](http://localhost:8080/SpringMVC4View/xStream/view/doListXMLXStream.do) 结果如下: ~~~ <list> <myBeans><id>1</id><name>haha#0</name><email>email0@120.com</email><address>北京#0</address><生日> <brithday>2010-11-20</brithday></生日></myBeans> <com.hoo.entity.User><name>jack#0</name><age>23</age><sex>false</sex><address>china GuangZhou 广州# 0</address> <brithday>2011-04-27 19:08:40.106 CST</brithday></com.hoo.entity.User> <myBeans><id>2</id><name>haha#1</name><email>email1@121.com</email><address>北京#1</address><生日> <brithday>2010-11-21</brithday></生日></myBeans> <com.hoo.entity.User><name>jack#1</name><age>24</age><sex>false</sex><address>china GuangZhou 广州# 1</address> <brithday>2011-04-27 19:08:40.106 CST</brithday></com.hoo.entity.User> <myBeans><id>3</id><name>haha#2</name><email>email2@122.com</email><address>北京#2</address><生日> <brithday>2010-11-22</brithday></生日></myBeans> <com.hoo.entity.User><name>jack#2</name><age>25</age><sex>false</sex><address>china GuangZhou 广州# 2</address> <brithday>2011-04-27 19:08:40.106 CST</brithday></com.hoo.entity.User></list> ~~~ 总结,xStream相对jaxb2要简单些。而且相对比较灵活,可以轻易的转换Java普通类型。 下次会介绍castor转换XML、jibx转换XML、Jackson转换JSON 以及自定义Jsonlib视图转换Json。
';

Java 的JSON、XML转换方法——目录索引

最后更新于:2022-04-01 14:22:28

JSON及XML的Java序列化、反序列化(转换)在WebService、Ajax数据传递中, 用得比较多。如:在用ExtJS、jQuery、mootools以及一些WebService时,你可以需要用到JSON、XML, 给前端传递JSON或XML数据。这个时候你就可以用下面的这些技术帮助你转换Java对象,这些技术都 可以轻易完成。比你手动拼接字符前要方便、省事得多。JSON的传递数据相对XML要更快些, 且性能更好,但XML的可读性更清晰。至于用JSON,还是XML就看你的需求了。   json-lib框架,可以完成Java对象到JSON的相互转换,以及简单转换XML。 在线博文: For cnblogs:[http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html](http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html) For csdn: [http://blog.csdn.net/IBM_hoojo/archive/2011/04/21/6339246.aspx](http://blog.csdn.net/IBM_hoojo/archive/2011/04/21/6339246.aspx)   Jackson框架,可以很方便的完成Java对象和JSON的相互转换。也可以完成xml转换,但是还不是那么的完善。 在线博文: For cnblogs:[http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html) For csdn:[http://blog.csdn.net/IBM_hoojo/archive/2011/04/22/6340762.aspx](http://blog.csdn.net/IBM_hoojo/archive/2011/04/22/6340762.aspx)   XStream对JSON、XML的都支持,它可以对JSON或XML的完美转换。 在线博文: For csblogs:[http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html) For csdn:[http://blog.csdn.net/IBM_hoojo/archive/2011/04/22/6342386.aspx](http://blog.csdn.net/IBM_hoojo/archive/2011/04/22/6342386.aspx)   用Castor来完成Java对象到xml的相互转换。 在线博文: for csblogs:[http://www.cnblogs.com/hoojo/archive/2011/04/25/2026819.html](http://www.cnblogs.com/hoojo/archive/2011/04/25/2026819.html) for csdn:[http://blog.csdn.net/IBM_hoojo/archive/2011/04/25/6360916.aspx](http://blog.csdn.net/IBM_hoojo/archive/2011/04/25/6360916.aspx)   Jaxb2完成xml的转换 在线博文: For cnblogs:[http://www.cnblogs.com/hoojo/archive/2011/04/26/2029011.html](http://www.cnblogs.com/hoojo/archive/2011/04/26/2029011.html) For csdn:[http://blog.csdn.net/IBM_hoojo/archive/2011/04/26/6363491.aspx](http://blog.csdn.net/IBM_hoojo/archive/2011/04/26/6363491.aspx)   Jibx完成Java到XML的相互转换 在线博文: For cnblogs:[http://www.cnblogs.com/hoojo/archive/2011/04/27/2030205.html](http://www.cnblogs.com/hoojo/archive/2011/04/27/2030205.html) For csdn:[http://blog.csdn.net/IBM_hoojo/archive/2011/04/27/6366333.aspx](http://blog.csdn.net/IBM_hoojo/archive/2011/04/27/6366333.aspx)
';

Jibx 处理XML

最后更新于:2022-04-01 14:22:26

前面有介绍过json-lib这个框架,在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html](http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html) 以及Jackson这个框架,在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html) 它们都可以完成Java对象到XML的转换,但是还不是那么的完善。 还有XStream对JSON及XML的支持,它可以对JSON或XML的完美转换。在线博文: [http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html) 以及介绍Castor来完成Java对象到xml的相互转换。在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/25/2026819.html](http://www.cnblogs.com/hoojo/archive/2011/04/25/2026819.html) Jaxb2完成xml的转换,在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/26/2029011.html](http://www.cnblogs.com/hoojo/archive/2011/04/26/2029011.html) Jibx对Java对象的转换相对要负责些,它不仅需要配置xml还且还要生成相应的jar文件,已经xsd文件。下面我们就来慢慢看看Jibx转换Java到XML是如何完成的。 ### 一、准备工作 1、 准备资源 a) 官方示例:[http://jibx.sourceforge.net/fromcode/bindgen-examples.html](http://jibx.sourceforge.net/fromcode/bindgen-examples.html) [http://www.java2s.com/Open-Source/Java/XML/JiBX/tutorial/Catalogtutorial.htm](http://www.java2s.com/Open-Source/Java/XML/JiBX/tutorial/Catalogtutorial.htm) b) Jar下载:[http://sourceforge.net/projects/jibx/files/](http://sourceforge.net/projects/jibx/files/) c) 依赖jar包如下: [![clip_image002](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-15_57105c48a8b13.gif "clip_image002")](http://hi.csdn.net/attachment/201104/27/0_1303875308wJ6L.gif) 2、 程序准备代码 ~~~ package com.hoo.test; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.jibx.runtime.BindingDirectory; import org.jibx.runtime.IBindingFactory; import org.jibx.runtime.IMarshallingContext; import org.jibx.runtime.IUnmarshallingContext; import org.jibx.runtime.JiBXException; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.hoo.entity.Account; import com.hoo.entity.AccountArray; import com.hoo.entity.Birthday; import com.hoo.entity.ListBean; import com.hoo.entity.MapBean; /** * function: Jibx转换Java到XML * @author hoojo * @createDate 2011-4-25 下午06:47:33 * @file JibxTest.java * @package com.hoo.test * @project WebHttpUtils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class JibxTest { private IBindingFactory factory = null; private StringWriter writer = null; private StringReader reader = null; private Account bean = null; @Before public void init() { bean = new Account(); bean.setAddress("北京"); bean.setEmail("email"); bean.setId(1); bean.setName("jack"); Birthday day = new Birthday(); day.setBirthday("2010-11-22"); bean.setBirthday(day); try { factory = BindingDirectory.getFactory(Account.class); } catch (JiBXException e) { e.printStackTrace(); } } @After public void destory() { bean = null; try { if (writer != null) { writer.flush(); writer.close(); } if (reader != null) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } System.gc(); } public void fail(Object o) { System.out.println(o); } public void failRed(Object o) { System.err.println(o); } } ~~~ IBindingFactory是一个工厂接口,通过BindingDirectory的getFactory工厂方法可以获得某个对象。然后通过这个工程可以获得转换xml文档的上下文。 ### 二、转换Java到XML、转换XML到Java 1、 转换JavaEntity对象 a) 首先看看Account、Birthday的代码 ~~~ package com.hoo.entity; public class Account { private int id; private String name; private String email; private String address; private Birthday birthday; //getter、setter @Override public String toString() { return this.id + "#" + this.name + "#" + this.email + "#" + this.address + "#" + this.birthday; } } ~~~ Birthday ~~~ package com.hoo.entity; public class Birthday { private String birthday; public Birthday(String birthday) { super(); this.birthday = birthday; } //getter、setter public Birthday() {} @Override public String toString() { return this.birthday; } } ~~~ b) 程序代码 ~~~ @Test public void bean2XML() { try { writer = new StringWriter(); // marshal 编组 IMarshallingContext mctx = factory.createMarshallingContext(); mctx.setIndent(2); mctx.marshalDocument(bean, "UTF-8", null, writer); fail(writer); reader = new StringReader(writer.toString()); //unmarshal 解组 IUnmarshallingContext uctx = factory.createUnmarshallingContext(); Account acc = (Account) uctx.unmarshalDocument(reader, null); fail(acc); } catch (Exception e) { e.printStackTrace(); } } ~~~ 这样还不够,复杂的东西还在后面。Jibx转换XML文档还要经过一系列复杂的程序。 c) 首先,要写bind.xml和schema。不过还好,官方有提高工具类可以用。 org.jibx.binding.generator.BindGen或org.jibx.binding.BindingGenerator这两个类都可以,用法如下: 首先用dos进入当前工程目录,然后执行命令:E:/Study/WebHttpUtils>java -cp bin;lib/jibx-tools.jar;lib/log4j-1.2.16.jar org.jibx.binding.generator.BindGen -b bind.xml com.hoo.entity.Account 上面的java 是运行某个程序 –cp是依赖的classpath路径的jar、zip等文件,-b 是输出文件名称,是BindGen类的参数。这样会在当前工程目录中生成bind.xml和entity.xsd文件。先看看这2个文件 bind.xml ~~~ <?xml version="1.0" encoding="UTF-8"?> <binding value-style="attribute"> <mapping class="com.hoo.entity.Account" name="account"> <value name="id" field="id"/> <value style="element" name="name" field="name" usage="optional"/> <value style="element" name="email" field="email" usage="optional"/> <value style="element" name="address" field="address" usage="optional"/> <structure field="birthday" usage="optional" name="birthday"> <value style="element" name="birthday" field="birthday" usage="optional"/> </structure> </mapping> </binding> ~~~ entity.xsd文件 ~~~ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://hoo.com/entity" elementFormDefault="qualified" targetNamespace="http://hoo.com/entity"> <xs:element type="tns:account" name="account"/> <xs:complexType name="account"> <xs:sequence> <xs:element type="xs:string" name="name" minOccurs="0"/> <xs:element type="xs:string" name="email" minOccurs="0"/> <xs:element type="xs:string" name="address" minOccurs="0"/> <xs:element name="birthday" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element type="xs:string" name="birthday" minOccurs="0"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute type="xs:int" use="required" name="id"/> </xs:complexType> </xs:schema> ~~~ 上面最重要的就是bind.xml文件了,下面编译的时候需要这个文件。Xsd文件可以根据这个文件的内容生成Java的Entity类代码。 执行完命令后,没有错误就可以运行下面一段命令了。运行命令: E:/Study/WebHttpUtils>java -cp bin;lib/jibx-bind.jar org.jibx.binding.Compile -v bind.xml -v是绑定文件的名称 运行后,有如下结果: [![clip_image004](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-15_57105c48bd1a2.gif "clip_image004")](http://hi.csdn.net/attachment/201104/27/0_1303875324YYOR.gif) d) 然后你就可以运行上面的Java的Junit测试程序了,运行后结果如下: ~~~ <?xml version="1.0" encoding="UTF-8"?> <account xmlns="http://hoo.com/entity" id="1"> <name>jack</name> <email>email</email> <address>北京</address> <birthday> <birthday>2010-11-22</birthday> </birthday> </account> 1#jack#email#北京#2010-11-22 ~~~ 你还可以用命令来查看某个已经生成bind、schema文件的信息,如: java -cp bin;lib/jibx-run.jar org.jibx.runtime.PrintInfo -c com.hoo.entity.Account 结果如下: [![clip_image006](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-15_57105c48d1cc7.gif "clip_image006")](http://hi.csdn.net/attachment/201104/27/0_13038753307lF2.gif) e) 注意,有时候会出现异常信息,如:java.lang.NoSuchFieldException: JiBX_bindingXXXX就要重复下面的命令就可以了。 java -cp bin;lib/jibx-bind.jar org.jibx.binding.Compile -v bind.xml 2、 转换带List集合属性的JavaBean a) 程序代码 ~~~ @Test public void listBean2XML() { try { ListBean listBean = new ListBean(); List list = new ArrayList(); list.add(bean); bean = new Account(); bean.setAddress("china"); bean.setEmail("tom@125.com"); bean.setId(2); bean.setName("tom"); Birthday day = new Birthday("2010-11-22"); bean.setBirthday(day); list.add(bean); listBean.setList(list); writer = new StringWriter(); factory = BindingDirectory.getFactory(ListBean.class); // marshal 编组 IMarshallingContext mctx = factory.createMarshallingContext(); mctx.setIndent(2); mctx.marshalDocument(listBean, "UTF-8", null, writer); fail(writer); reader = new StringReader(writer.toString()); //unmarshal 解组 IUnmarshallingContext uctx = factory.createUnmarshallingContext(); listBean = (ListBean) uctx.unmarshalDocument(reader, null); fail(listBean.getList().get(0)); fail(listBean.getList().get(1)); } catch (Exception e) { e.printStackTrace(); } } ~~~ b) ListBean代码 ~~~ package com.hoo.entity; import java.util.List; public class ListBean { private String name; private List list; } ~~~ c) 生成bind.xml 执行dos命令: java -cp bin;lib/jibx-tools.jar;lib/log4j-1.2.16.jar org.jibx.binding.BindingGenerator -f bind.xml com.hoo.entity.ListBean 输出: [![clip_image008](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-15_57105c48e3c5d.gif "clip_image008")](http://hi.csdn.net/attachment/201104/27/0_1303875331rAMa.gif) d) 执行完后会生产bind.xml Bind文件 ~~~ <?xml version="1.0" encoding="UTF-8"?> <binding value-style="attribute"> <mapping class="com.hoo.entity.ListBean" name="list-bean"> <value style="element" name="name" field="name" usage="optional"/> <collection field="list" usage="optional" factory="org.jibx.runtime.Utility.arrayListFactory"/> </mapping> </binding> ~~~ e) 运行Compile工具类 在运行前,一定要将最先前运行的Account那个类的bind.xml文件的内容加入到现在这个bind.xml中,因为ListBean依赖了Account这个类。 命令如下: java -cp bin;lib/jibx-bind.jar org.jibx.binding.Compile -v bind.xml 运行后你可以看到最后出现这个 [![clip_image010](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-15_57105c49055c7.gif "clip_image010")](http://hi.csdn.net/attachment/201104/27/0_130387533372oI.gif) f) 运行Test程序,结果如下: ~~~ <?xml version="1.0" encoding="UTF-8"?> <list-bean> <account id="1"> <name>jack</name> <email>email</email> <address>北京</address> <birthday> <birthday>2010-11-22</birthday> </birthday> </account> <account id="2"> <name>tom</name> <email>tom@125.com</email> <address>china</address> <birthday> <birthday>2010-11-22</birthday> </birthday> </account> </list-bean> 1#jack#email#北京#2010-11-22 2#tom#tom@125.com#china#2010-11-22 ~~~ 3、 转换Java对象数组 a) Test程序 ~~~ /** * function:转换对象数组 * @author hoojo * @createDate 2011-4-26 下午05:32:03 */ @Test public void arrayBean2XML() { try { Account[] acc = new Account[2]; acc[0] = bean; bean = new Account(); bean.setName("tom"); bean.setId(223); acc[1] = bean; AccountArray array = new AccountArray(); array.setAccounts(acc); writer = new StringWriter(); factory = BindingDirectory.getFactory(AccountArray.class); // marshal 编组 IMarshallingContext mctx = factory.createMarshallingContext(); mctx.setIndent(2); mctx.marshalDocument(array, "UTF-8", null, writer); fail(writer); reader = new StringReader(writer.toString()); //unmarshal 解组 IUnmarshallingContext uctx = factory.createUnmarshallingContext(); array = (AccountArray) uctx.unmarshalDocument(reader, null); fail(array.getAccounts()[0]); fail(array.getAccounts()[1]); } catch (Exception e) { e.printStackTrace(); } } ~~~ b) AccountArray代码 ~~~ package com.hoo.entity; public class AccountArray { private Account[] accounts; private int size; public int getSize() { size = accounts.length; return size; } public void setSize(int size) { this.size = size; } public Account[] getAccounts() { return accounts; } public void setAccounts(Account[] accounts) { this.accounts = accounts; } } ~~~ c) 运行命令生成bind.xml文件 命令如下: java -cp bin;lib/jibx-tools.jar;lib/log4j-1.2.16.jar org.jibx.binding.BindingGenerator -f bind.xml com.hoo.entity.Account com.hoo.entity.AccountArray 因为AccountArray依赖Account,所以后面带2个类 [![clip_image012](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-15_57105c4919059.gif "clip_image012")](http://hi.csdn.net/attachment/201104/27/0_1303875335gyP4.gif) d) 运行Compile命令 java -cp bin;lib/jibx-bind.jar org.jibx.binding.Compile -v bind.xml e) 执行完后,就可以运行Test程序了,结果如下 ~~~ <?xml version="1.0" encoding="UTF-8"?> <account-array size="0"> <account id="1"> <name>jack</name> <email>email</email> <address>北京</address> <birthday> <birthday>2010-11-22</birthday> </birthday> </account> <account id="223"> <name>tom</name> </account> </account-array> 1#jack#email#北京#2010-11-22 223#tom#null#null#null ~~~ 4、 转换带Map结合的JavaEntity对象 a) Test代码 ~~~ /** * function:转换Map集合 * @author hoojo * @createDate 2011-4-26 下午05:40:34 */ @Test public void mapBean2XML() { try { MapBean mapBean = new MapBean(); HashMap map = new HashMap(); map.put("No1", bean); bean = new Account(); bean.setAddress("china"); bean.setEmail("tom@125.com"); bean.setId(2); bean.setName("tom"); Birthday day = new Birthday("2010-11-22"); bean.setBirthday(day); map.put("No2", bean); mapBean.setMap(map); factory = BindingDirectory.getFactory(MapBean.class); writer = new StringWriter(); // marshal 编组 IMarshallingContext mctx = factory.createMarshallingContext(); mctx.setIndent(2); mctx.marshalDocument(mapBean, "UTF-8", null, writer); fail(writer); reader = new StringReader(writer.toString()); //unmarshal 解组 IUnmarshallingContext uctx = factory.createUnmarshallingContext(); mapBean = (MapBean) uctx.unmarshalDocument(reader, null); fail(mapBean.getMap()); fail(mapBean.getMap().get("No1")); fail(mapBean.getMap().get("No2")); } catch (Exception e) { e.printStackTrace(); } } ~~~ b) MapBean代码 ~~~ package com.hoo.entity; import java.util.HashMap; public class MapBean { private HashMap map; public HashMap getMap() { return map; } public void setMap(HashMap map) { this.map = map; } } ~~~ c) 生成bind.xml,命令如下 E:/Study/WebHttpUtils>java -cp bin;lib/jibx-tools.jar;lib/log4j-1.2.16.jar org.jibx.binding.BindingGenerator -f bind.xml com.hoo.entity.Account com.hoo.entity.MapBean 运行后,会生产bind.xml;修改bind.xml内容如下: ~~~ <?xml version="1.0" encoding="UTF-8"?> <binding value-style="attribute"> <mapping class="com.hoo.entity.Account" name="account"> <value name="id" field="id" /> <value style="element" name="name" field="name" usage="optional" /> <value style="element" name="email" field="email" usage="optional" /> <value style="element" name="address" field="address" usage="optional" /> <structure field="birthday" usage="optional" name="birthday"> <value style="element" name="birthday" field="birthday" usage="optional" /> </structure> </mapping> <mapping class="com.hoo.entity.MapBean" name="map-bean"> <structure field="map" usage="optional" name="map" marshaller="com.hoo.util.HashMapper" unmarshaller="com.hoo.util.HashMapper"> </structure> </mapping> </binding> ~~~ 注意上面的MapBean的structure元素的内容是经过修改的。一定要带上marshaller或unmarshaller,不然无法转换HashMap的。 d) HashMapper代码 ~~~ package com.hoo.util; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.jibx.runtime.IAliasable; import org.jibx.runtime.IMarshallable; import org.jibx.runtime.IMarshaller; import org.jibx.runtime.IMarshallingContext; import org.jibx.runtime.IUnmarshaller; import org.jibx.runtime.IUnmarshallingContext; import org.jibx.runtime.JiBXException; import org.jibx.runtime.impl.MarshallingContext; import org.jibx.runtime.impl.UnmarshallingContext; /** * function:http://www.java2s.com/Open-Source/Java/XML/JiBX/tutorial/example21/HashMapper.java.htm * @file HashMapper.java * @package com.hoo.util * @project WebHttpUtils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class HashMapper implements IMarshaller, IUnmarshaller, IAliasable { private static final String SIZE_ATTRIBUTE_NAME = "size"; private static final String ENTRY_ELEMENT_NAME = "entry"; private static final String KEY_ATTRIBUTE_NAME = "key"; private static final int DEFAULT_SIZE = 10; private String m_uri; private int m_index; private String m_name; public HashMapper() { m_uri = null; m_index = 0; m_name = "hashmap"; } public HashMapper(String uri, int index, String name) { m_uri = uri; m_index = index; m_name = name; } /* (non-Javadoc) * @see org.jibx.runtime.IMarshaller#isExtension(int) */ public boolean isExtension(int index) { return false; } /* (non-Javadoc) * @see org.jibx.runtime.IMarshaller#marshal(java.lang.Object, * org.jibx.runtime.IMarshallingContext) */ public void marshal(Object obj, IMarshallingContext ictx) throws JiBXException { // make sure the parameters are as expected if (!(obj instanceof HashMap)) { throw new JiBXException("Invalid object type for marshaller"); } else if (!(ictx instanceof MarshallingContext)) { throw new JiBXException("Invalid object type for marshaller"); } else { // start by generating start tag for container MarshallingContext ctx = (MarshallingContext)ictx; HashMap map = (HashMap)obj; ctx.startTagAttributes(m_index, m_name). attribute(m_index, SIZE_ATTRIBUTE_NAME, map.size()). closeStartContent(); // loop through all entries in hashmap Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry)iter.next(); ctx.startTagAttributes(m_index, ENTRY_ELEMENT_NAME); if (entry.getKey() != null) { ctx.attribute(m_index, KEY_ATTRIBUTE_NAME, entry.getKey().toString()); } ctx.closeStartContent(); if (entry.getValue() instanceof IMarshallable) { ((IMarshallable)entry.getValue()).marshal(ctx); ctx.endTag(m_index, ENTRY_ELEMENT_NAME); } else { throw new JiBXException("Mapped value is not marshallable"); } } // finish with end tag for container element ctx.endTag(m_index, m_name); } } /* (non-Javadoc) * @see org.jibx.runtime.IUnmarshaller#isPresent(org.jibx.runtime.IUnmarshallingContext) */ public boolean isPresent(IUnmarshallingContext ctx) throws JiBXException { return ctx.isAt(m_uri, m_name); } /* (non-Javadoc) * @see org.jibx.runtime.IUnmarshaller#unmarshal(java.lang.Object, * org.jibx.runtime.IUnmarshallingContext) */ public Object unmarshal(Object obj, IUnmarshallingContext ictx) throws JiBXException { // make sure we're at the appropriate start tag UnmarshallingContext ctx = (UnmarshallingContext)ictx; if (!ctx.isAt(m_uri, m_name)) { ctx.throwStartTagNameError(m_uri, m_name); } // create new hashmap if needed int size = ctx.attributeInt(m_uri, SIZE_ATTRIBUTE_NAME, DEFAULT_SIZE); HashMap map = (HashMap)obj; if (map == null) { map = new HashMap(size); } // process all entries present in document ctx.parsePastStartTag(m_uri, m_name); while (ctx.isAt(m_uri, ENTRY_ELEMENT_NAME)) { Object key = ctx.attributeText(m_uri, KEY_ATTRIBUTE_NAME, null); ctx.parsePastStartTag(m_uri, ENTRY_ELEMENT_NAME); Object value = ctx.unmarshalElement(); map.put(key, value); ctx.parsePastEndTag(m_uri, ENTRY_ELEMENT_NAME); } ctx.parsePastEndTag(m_uri, m_name); return map; } public boolean isExtension(String arg0) { return false; } } ~~~ e) 然后运行Compile命令 E:/Study/WebHttpUtils>java -cp bin;lib/jibx-bind.jar org.jibx.binding.Compile -v bind.xml f) 结果如下 ~~~ <?xml version="1.0" encoding="UTF-8"?> <map-bean> <map size="2"> <entry key="No2"> <account id="2"> <name>tom</name> <email>tom@125.com</email> <address>china</address> <birthday> <birthday>2010-11-22</birthday> </birthday> </account> </entry> <entry key="No1"> <account id="1"> <name>jack</name> <email>email</email> <address>北京</address> <birthday> <birthday>2010-11-22</birthday> </birthday> </account> </entry> </map> </map-bean> {No2=2#tom#tom@125.com#china#2010-11-22, No1=1#jack#email#北京#2010-11-22} 1#jack#email#北京#2010-11-22 2#tom#tom@125.com#china#2010-11-22 ~~~
';

Jaxb2 转换XML文档

最后更新于:2022-04-01 14:22:23

——完成Java对象和XML相互转换 前面有介绍过json-lib这个框架,在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html](http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html) 以及Jackson这个框架,在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html) 它们都可以完成Java对象到XML的转换,但是还不是那么的完善。 还有XStream对JSON及XML的支持,它可以对JSON或XML的完美转换。在线博文: [http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html) 以及介绍Castor来完成Java对象到xml的相互转换。在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/25/2026819.html](http://www.cnblogs.com/hoojo/archive/2011/04/25/2026819.html) 这次介绍Jaxb2完成xml的转换,Jaxb2使用了JDK的新特性。如:Annotation、GenericType等,Jaxb2需要在即将转换的JavaBean中添加annotation注解。下面我们就来看看Jaxb2是怎么样完成Java对象到XML之间的相互转换吧。 ### 一、准备工作 1、 资源准备 a) 官方文档:[http://www.oracle.com/technetwork/articles/javase/index-140168.html](http://www.oracle.com/technetwork/articles/javase/index-140168.html) b) Jar包下载:[http://jaxb.java.net/2.2.3/JAXB2_20101209.jar](http://jaxb.java.net/2.2.3/JAXB2_20101209.jar) 如果你有添加jdk的jar到工程中,在rt.jar中就带有jaxb2。一般情况下不用自己添加jaxb2的jar。 2、 程序前代码准备 ~~~ package com.hoo.test; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.hoo.entity.Account; import com.hoo.entity.AccountBean; import com.hoo.entity.Birthday; import com.hoo.entity.ListBean; import com.hoo.entity.MapBean; /** * function:Jaxb2 完成Java和XML的编组、解组 * @author hoojo * @createDate 2011-4-25 上午11:54:06 * @file Jaxb2Test.java * @package com.hoo.test * @project WebHttpUtils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class Jaxb2Test { private JAXBContext context = null; private StringWriter writer = null; private StringReader reader = null; private AccountBean bean = null; @Before public void init() { bean = new AccountBean(); bean.setAddress("北京"); bean.setEmail("email"); bean.setId(1); bean.setName("jack"); Birthday day = new Birthday(); day.setBirthday("2010-11-22"); bean.setBirthday(day); try { context = JAXBContext.newInstance(AccountBean.class); } catch (Exception e) { e.printStackTrace(); } } @After public void destory() { context = null; bean = null; try { if (writer != null) { writer.flush(); writer.close(); } if (reader != null) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } System.gc(); } public void fail(Object o) { System.out.println(o); } public void failRed(Object o) { 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 public void testBean2XML() { try { //下面代码演示将对象转变为xml Marshaller mar = context.createMarshaller(); writer = new StringWriter(); mar.marshal(bean, writer); fail(writer); //下面代码演示将上面生成的xml转换为对象 reader = new StringReader(writer.toString()); Unmarshaller unmar = context.createUnmarshaller(); bean = (AccountBean)unmar.unmarshal(reader); fail(bean); } catch (JAXBException e) { e.printStackTrace(); } } ~~~ 上面的context是在init方法中创建的,它传递了一个AccountBean的class,这个AccountBean不是一般的普通的bean。除了它带有getter、setter方法外,还有Annotation注解。下面我们就看看这个bean的代码。 ~~~ package com.hoo.entity; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; import com.sun.xml.internal.txw2.annotation.XmlElement; @XmlRootElement(name = "account") public class AccountBean { private int id; private String name; private String email; private String address; private Birthday birthday; @XmlElement public Birthday getBirthday() { return birthday; } public void setBirthday(Birthday birthday) { this.birthday = birthday; } @XmlAttribute(name = "number") public int getId() { return id; } public void setId(int id) { this.id = id; } @XmlElement public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElement public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return this.name + "#" + this.id + "#" + this.address + "#" + this.birthday + "#" + this.email; } } ~~~ 上面的XmlRootElement是设置当前对象转换成xml后的根节点,name的值是设置根节点的名称。在getter方法上设置XmlElement表示这个方法对应的属性是一个xml元素,如果这个注解还设置了name,那么这个name就是转换后xml的名称。在一个属性上设置XmlAttribute,表示这个方法对应的属性在转换xml后是父元素的一个属性。XmlAttribute的name就是转换后xml的属性的name。 运行后,结果如下: ~~~ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>"1"> 北京 2010-11-22emailjack jack#1#北京#2010-11-22#email ~~~ 把转换后的xml和上面的AccountBean对应看看 2、 对List类型对象,进行编组、解组 ~~~ @Test public void testList2XML() { ListBean listBean = new ListBean(); listBean.setName("list to xml"); List<Object> list = new ArrayList<Object>(); list.add(bean); bean = new AccountBean(); bean.setAddress("china"); bean.setEmail("tom@125.com"); bean.setId(2); bean.setName("tom"); Birthday day = new Birthday("2010-11-22"); bean.setBirthday(day); Account acc = new Account(); acc.setAddress("china"); acc.setEmail("tom@125.com"); acc.setId(2); acc.setName("tom"); day = new Birthday("2010-11-22"); acc.setBirthday(day); list.add(bean); list.add(acc); listBean.setList(list); try { context = JAXBContext.newInstance(ListBean.class); //下面代码演示将对象转变为xml Marshaller mar = context.createMarshaller(); writer = new StringWriter(); mar.marshal(listBean, writer); fail(writer); //下面代码演示将上面生成的xml转换为对象 reader = new StringReader(writer.toString()); Unmarshaller unmar = context.createUnmarshaller(); listBean = (ListBean)unmar.unmarshal(reader); fail(listBean.getList().get(0)); fail(listBean.getList().get(1)); fail(listBean.getList().get(2)); } catch (JAXBException e) { e.printStackTrace(); } } ~~~ 你不能直接new 一个List,然后将对象放到List中。进行编组、解组,这样会出现异常情况的。你需要构建一个JavaBean,在bean中创建一个List的属性。然后在这个属性的getter方法上进行Annotation注解。下面我们看看ListBean的代码: ~~~ package com.hoo.entity; import java.util.List; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlRootElement; @SuppressWarnings("unchecked") @XmlRootElement(name = "list-bean") public class ListBean { private String name; private List list; @XmlElements({ @XmlElement(name = "account", type = Account.class), @XmlElement(name = "bean", type = AccountBean.class) }) public List getList() { return list; } public void setList(List list) { this.list = list; } @XmlAttribute public String getName() { return name; } public void setName(String name) { this.name = name; } } ~~~ XmlElements表示是一个集合类型,然后注解在集合中存放上面类型的对象。 XmlElement表示在集合中存放的一个对象类型和元素名称。 转换后结果如下: ~~~ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <list-bean name="list to xml"> <bean number="1"><address>北京</address><birthday><birthday>2010-11-22</birthday></birthday> <email>email</email><name>jack</name></bean> <bean number="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对象实现 * http://metro.1045641.n5.nabble.com/Does-JAXB-2-0-support-Map-td1058084.html * @author hoojo * @createDate 2010-12-1 上午10:23:26 */ @Test public void testMap2XML() { MapBean mapBean = new MapBean(); HashMap<String, AccountBean> map = new HashMap<String, AccountBean>(); map.put("NO1", bean); bean = new AccountBean(); bean.setAddress("china"); bean.setEmail("tom@125.com"); bean.setId(2); bean.setName("tom"); Birthday day = new Birthday("2010-11-22"); bean.setBirthday(day); map.put("NO2", bean); mapBean.setMap(map); try { context = JAXBContext.newInstance(MapBean.class); //下面代码演示将对象转变为xml Marshaller mar = context.createMarshaller(); writer = new StringWriter(); mar.marshal(mapBean, writer); fail(writer); //下面代码演示将上面生成的xml转换为对象 reader = new StringReader(writer.toString()); Unmarshaller unmar = context.createUnmarshaller(); mapBean = (MapBean)unmar.unmarshal(reader); fail(mapBean.getMap()); } catch (JAXBException e) { e.printStackTrace(); } } ~~~ 下面看看MapBean的代码 ~~~ package com.hoo.entity; import java.util.HashMap; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import com.hoo.util.MapAdapter; @XmlRootElement public class MapBean { private HashMap<String, AccountBean> map; @XmlJavaTypeAdapter(MapAdapter.class) public HashMap<String, AccountBean> getMap() { return map; } public void setMap(HashMap<String, AccountBean> map) { this.map = map; } } ~~~ 上面的map集合的getter方法有一个XmlJavaTypeAdapter,需要传递一个Adapter的类型。 下面看看MyAdapter的代码 ~~~ package com.hoo.util; import java.util.HashMap; import java.util.Map; import javax.xml.bind.annotation.adapters.XmlAdapter; import com.hoo.entity.AccountBean; /** * <b>function:</b>AccountBean 编组、解组的XmlAdapter * @author hoojo * @createDate 2011-4-25 下午05:03:18 * @file MyAdetper.java * @package com.hoo.util * @project WebHttpUtils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class MapAdapter extends XmlAdapter<MapElements[], Map<String, AccountBean>> { public MapElements[] marshal(Map<String, AccountBean> arg0) throws Exception { MapElements[] mapElements = new MapElements[arg0.size()]; int i = 0; for (Map.Entry<String, AccountBean> entry : arg0.entrySet()) mapElements[i++] = new MapElements(entry.getKey(), entry.getValue()); return mapElements; } public Map<String, AccountBean> unmarshal(MapElements[] arg0) throws Exception { Map<String, AccountBean> r = new HashMap<String, AccountBean>(); for (MapElements mapelement : arg0) r.put(mapelement.key, mapelement.value); return r; } } ~~~ MapElements ~~~ package com.hoo.util; import javax.xml.bind.annotation.XmlElement; import com.hoo.entity.AccountBean; /** * <b>function:</b> MapElements * @author hoojo * @createDate 2011-4-25 下午05:04:04 * @file MyElements.java * @package com.hoo.util * @project WebHttpUtils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class MapElements { @XmlElement public String key; @XmlElement public AccountBean value; @SuppressWarnings("unused") private MapElements() { } // Required by JAXB public MapElements(String key, AccountBean value) { this.key = key; this.value = value; } } ~~~ 运行结果如下: ~~~ <?xml version="1.0" encoding="UTF-8" standalone="yes"?><mapBean><map><item><key>NO2</key><value number="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><value number="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} ~~~
';

Castor 完成Java解组、XML编组

最后更新于:2022-04-01 14:22:21

——Castor可以完成Java和XML的相互转换 前面有介绍过json-lib这个框架,在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html](http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html) 以及Jackson这个框架,在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html) 它们都可以完成Java对象到XML的转换,但是还不是那么的完善。还有XStream对JSON及XML的支持,它可以对JSON或XML的完美转换。在线博文: [http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html) 这里将介绍Castor来完成Java对象到xml的相互转换。它是怎么样转换的?和前面不同的是castor可以用一个mapping.xml文件来描述转换后的Java对象的xml基本形态,类似于xStream的annotation,这点还是非常不错的。下面我们就来看看Castor是怎么样完成Java对象到XML之间的相互转换吧。 ### 一、准备工作 1、 官方资源 本示例会运用到如下依赖包(jar包): [![clip_image002](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-15_57105c4893965.gif "clip_image002")](http://hi.csdn.net/attachment/201104/25/0_13036993615eBC.gif) 资源及jar包下载:[http://www.castor.org/download.html](http://www.castor.org/download.html) junit jar下载地址: [https://github.com/KentBeck/junit/downloads](https://github.com/KentBeck/junit/downloads) 关于官方提供的mapping配置相关示例、文档: [http://www.castor.org/xml-mapping.html](http://www.castor.org/xml-mapping.html) ibm提供的castor方面的文档资料: [http://www.google.com.hk/search?hl=zh-CN&newwindow=1&safe=strict&client=aff-cs-360se&hs=Gon&biw=1349&bih=603&q=castor+site%3Awww.ibm.com%2Fdeveloperworks%2Fcn%2Fxml%2F&aq=f&aqi=&aql=&oq](http://www.google.com.hk/search?hl=zh-CN&newwindow=1&safe=strict&client=aff-cs-360se&hs=Gon&biw=1349&bih=603&q=castor+site%3Awww.ibm.com%2Fdeveloperworks%2Fcn%2Fxml%2F&aq=f&aqi=&aql=&oq)= 2、 程序测试运行代码 ~~~ package com.hoo.test; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.mapping.MappingException; import org.exolab.castor.xml.MarshalException; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.Unmarshaller; import org.exolab.castor.xml.ValidationException; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.hoo.entity.Account; import com.hoo.entity.AccountArray; import com.hoo.entity.Birthday; import com.hoo.entity.ListBean; import com.hoo.entity.MapBean; /** * function:Castor完成Java对象到XML的相互转换 * 依赖jar: castor-1.3.jar * castor-1.3-core.jar * junit-4.8.2.jar * log4j-1.2.16.jar * commons-logging.jar * @author hoojo * @createDate 2011-4-21 下午07:57:26 * @file CastorTest.java * @package com.hoo.test * @project WebHttpUtils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ public class CastorTest { private Account bean = null; private Mapping mapping = new Mapping(); private StringWriter writer = null; private StringReader reader = null; @Before public void init() { bean = new Account(); bean.setAddress("北京"); bean.setEmail("email"); bean.setId(1); bean.setName("jack"); Birthday day = new Birthday(); day.setBirthday("2010-11-22"); bean.setBirthday(day); try { /** * 加载mapping.xml,此文件是对需要转换的Java对象的配置描述, * 即:转换后的Java对象的xml内容的转换规则 */ mapping.loadMapping(System.getProperty("user.dir") + "//src//mapping.xml"); } catch (IOException e) { e.printStackTrace(); } catch (MappingException e) { e.printStackTrace(); } } @After public void destory() { bean = null; mapping = null; try { if (writer != null) { writer.flush(); writer.close(); } if (reader != null) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } System.gc(); } public void fail(Object o) { System.out.println(o); } public void failRed(Object o) { System.err.println(o); } } ~~~ Mapping对象可以完成Java对象到XML的编组和解组,它需要先设定一个mapping.xml,通过xml对JavaObject的描述。来完成JavaObject的编组、解组工作。 3、 看看即将被转换的JavaEntity代码 Account ~~~ package com.hoo.entity; public class Account { private int id; private String name; private String email; private String address; private Birthday birthday; //setter、getter @Override public String toString() { return this.id + "#" + this.name + "#" + this.email + "#" + this.address + "#" + this.birthday; } } ~~~ Birthday ~~~ package com.hoo.entity; public class Birthday { private String birthday; public Birthday(String birthday) { super(); this.birthday = birthday; } //getter、setter public Birthday() {} @Override public String toString() { return this.birthday; } } ~~~ AccountArray ~~~ package com.hoo.entity; public class AccountArray { private Account[] accounts; private int size; public int getSize() { size = accounts.length; return size; } public void setSize(int size) { this.size = size; } public Account[] getAccounts() { return accounts; } public void setAccounts(Account[] accounts) { this.accounts = accounts; } } ~~~ ListBean ~~~ package com.hoo.entity; import java.util.List; public class ListBean { private String name; private List list; //setter、getter } ~~~ MapBean ~~~ package com.hoo.entity; import java.util.Map; public class MapBean { private Map map; public Map getMap() { return map; } public void setMap(Map map) { this.map = map; } } ~~~ ### 二、编组JavaObject到XML 1、 将JavaBean编组,转换成XML ~~~ /** * function:将Javabean编组,转换成XML * @author hoojo * @createDate 2011-4-22 下午12:08:48 */ @Test public void writeBean2XML() { writer = new StringWriter(); try { //编组 Marshaller.marshal(bean, writer); fail(writer); } catch (MarshalException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } ~~~ 代码很简单,通过Marshaller的marshal方法来完成Java对象到XML的编组(序列化、转换)工作。 运行后的结果如下: ~~~ "1.0" encoding="UTF-8"?> "1"> 北京 emailjack 2010-11-22 ~~~ 2、 将List集合转换成XML ~~~ /** * function:将List转换成xml * @author hoojo * @createDate 2011-4-22 下午12:11:00 */ @Test public void writeList2XML() { writer = new StringWriter(); List list = new ArrayList(); list.add(bean); bean = new Account(); bean.setName("tom"); bean.setId(223); list.add(bean); try { Marshaller.marshal(list, writer); fail(writer); } catch (MarshalException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } ~~~ 运行后,结果如下: ~~~ "1.0" encoding="UTF-8"?> "http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://java.sun.com" id="1" xsi:type="java:com.hoo.entity.Account"> 北京 emailjack2010-11-22 "http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://java.sun.com" id="223" xsi:type="java:com.hoo.entity.Account"> tom ~~~ 怎么样,List存放的是2个Account吧。 3、 将Array数组转换成XML ~~~ /** * function:将Array数组转换成XML * @author hoojo * @createDate 2011-4-22 下午12:11:25 */ @Test public void writeArray2XML() { writer = new StringWriter(); Account[] acc = new Account[2]; acc[0] = bean; bean = new Account(); bean.setName("tom"); bean.setId(223); acc[1] = bean; try { Marshaller.marshal(acc, writer); fail(writer); } catch (MarshalException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } ~~~ 结果如下: ~~~ "1.0" encoding="UTF-8"?> "1"> 北京 emailjack 2010-11-22 "223">tom ~~~ 4、 转换其他Java类型 ~~~ /** * function:将Java常用类型编组成xml * @author hoojo * @createDate 2011-4-22 下午12:11:44 */ @Test public void writeObject2XML() { writer = new StringWriter(); try { Marshaller.marshal(true, writer); Marshaller.marshal(9527, writer); Marshaller.marshal(2.2f, writer); Marshaller.marshal(1.11d, writer); Marshaller.marshal("lucy", writer); Marshaller.marshal("hello castor".getBytes(), writer); Marshaller.marshal(new char[] { 'a', 'b', 'c' }, writer); Marshaller.marshal(new String[] { "hi", "spring", "castor" }, writer); fail(writer); } catch (MarshalException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } ~~~ 结果如下: ~~~ "1.0" encoding="UTF-8"?> <boolean>trueboolean>"1.0" encoding="UTF-8"?> 9527"1.0" encoding="UTF-8"?> <float>2.2float>"1.0" encoding="UTF-8"?> <double>1.11double>"1.0" encoding="UTF-8"?> lucy"1.0" encoding="UTF-8"?> <[-b>aGVsbG8gY2FzdG9y"1.0" encoding="UTF-8"?> abc"1.0" encoding="UTF-8"?> hispringcastor ~~~ 都是类型为节点名称,值为text。但是这里并没有出现Map,如果转换Map需要mapping进行配置。下面再慢慢道来-.- 5、 将xml解组成JavaBean ~~~ /** * function:将XML内容,解组成JavaBean * @author hoojo * @createDate 2011-4-22 下午12:12:14 */ @Test public void readXML2Bean() { String xml = "" + " 北京 " + "jackemail" + "2010-11-22"; reader = new StringReader(xml); try { //解组 Account account = (Account) Unmarshaller.unmarshal(Account.class, reader); fail(account); } catch (MarshalException e) { e.printStackTrace(); } catch (ValidationException e) { e.printStackTrace(); } } ~~~ 结果如下: ~~~ 1#jack#email#北京#2010-11-22 ~~~ 其他的类型,如:map、list、array都不能成功解组。因为这些类型里面有很多系统默认的xml描述。但是利用mapping和自定义JavaBean就可以成功编组和解组了。下面看看mapping是怎么玩转这些类型的。 ### 三、利用mapping配置,编组JavaObject、解组XML 最开始的init方法就提供了mapping,让我们对mapping这个配置有了大概的了解。下面我们将详细介绍mapping是个什么: 1、 在此之前我们设置过mapping.xml。如果不设置,肯定是不能转换成我们想要的XML的。那么,mapping.xml配置文件是怎么配置Account这个对象的呢? mapping.xml配置如下: ~~~ xml version="1.0" encoding="UTF-8"?> DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.org/mapping.dtd"> <mapping> <class name="com.hoo.entity.Account" auto-complete="true"> <map-to xml="Account"/> <field name="id" type="integer"> <bind-xml name="id" node="attribute" /> </field> <field name="name" type="string"> <bind-xml name="name" node="element" /> </field> <field name="email" type="string"> <bind-xml name="email" node="element" /> </field> <field name="address" type="string"> <bind-xml name="address" node="element" /> </field> <field name="birthday" type="com.hoo.entity.Birthday"> <bind-xml name="生日" node="element" /> </field> </class> <class name="com.hoo.entity.Birthday"> <map-to xml="birthday" /> <field name="birthday" type="string"> <bind-xml name="birthday" node="attribute" /> </field> </class> </mapping> ~~~ 首先,看看这个xml文档的根元素是mapping,在mapping中可以配置class。也就是我们要转换的JavaObject的配置描述了。 class元素的name属性就是配置的JavaObject的classpath路径了。 关于class元素的auto-complate属性,如果这个属性的值为ture。那么编组后的xml,castor会自动给没有在mapping配置文件进行配置的属性自动编组(转换)到xml中。如果为false,那么在mapping配置文件中出现的属性将在编组后不现在在编组后的xml中。 map-to就是当前class编组后的xml文档的节点元素名称。 field就是描述JavaObject中的属性,name是Java对象的属性名称,type是类型。关于配置的type类型也有规定,你可以参考:[http://www.castor.org/xml-mapping.html的field](http://www.castor.org/xml-mapping.html的field)配置讲解。 而field还有其他的属性配置,如get-method应该是getter方法、set-method应该是setter的方法、has-mehtod应该是hashCode方法,有时候我们不一定要提高getter、setter方法,我们需要用自己的方法名称来代替setter、getter。如果当前field配置的是集合类型,那么你需要给field元素配置collection属性。 bind-xml就是绑定(编组)成xml后的xml内容的描述,name就是编组后xml的节点元素名称,node有2个值,分别是attribute、element。attribute是属性,它会在节点元素的属性中显示,例如: 而element则是单独的一个元素,例如:2 就这个样子的。 mapping.xml还可以有其他标签,如: 导入外部xml文件,可以分多个配置。 好了,先将这么多的mapping方面的内容。我们还是看看实际运行的示例吧,代码如下: ~~~ /** * function:将XML内容解组成Java对象 * @author hoojo * @createDate 2011-4-22 下午12:13:28 */ @Test public void bean4Mapping2XML() { writer = new StringWriter(); try { //编组 Marshaller mar = new Marshaller(writer); mar.setMapping(mapping); mar.marshal(bean); fail(writer); //解组 reader = new StringReader(writer.toString()); Unmarshaller unmar = new Unmarshaller(Account.class); unmar.setMapping(mapping); Account account = (Account) unmar.unmarshal(reader); fail(account); } catch (MarshalException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } ~~~ 运行后结果如下: ~~~ "1.0" encoding="UTF-8"?> "1">jackemail 北京 <生日 birthday="2010-11-22"/> 1#jack#email#北京#2010-11-22 ~~~ 上面的xml的根节点是Account,这个功劳就来源于mapping配置中的map-to元素,而根节点的id属性是有field和bind-xml来完成的。当bind-xml的node值为attribute时,就会以属性的方式显示。当node为element时,就会像后面name、email一样,以元素名称显示。 再看看上面的mapping文件中的Account的配置,有个auto-complate属性,如果把这个属性的值设置成false,会怎么样?那我们赶紧试试。 没有发现上面异样,但是当我们删除下面配置的filed的时候,就发现有变化了。 结果如下: ~~~ "1.0" encoding="UTF-8"?> jackemail 北京 <生日 birthday="2010-11-22"/> 0#jack#email#北京#2010-11-22 ~~~ 发现id没有显示在xml中,那么我们再将auto-complate的属性设置true,会有什么惊喜? 结果如下: ~~~ "1.0" encoding="UTF-8"?> "1">jackemail 北京 <生日 birthday="2010-11-22"/> 1#jack#email#北京#2010-11-22 ~~~ 发现id又回来了,但是Account的配置中并没有配置id的field。这是为什么,其实auto-comlate在上面已经讲过了。Castor在编组时会自动将int类型的属性,显示在父元素的属性中。并且JavaObject中有的属性没有在mapping配置文件中配置,castor也会自动将其编组在xml中。 下面我们看看map-to配置的用法,map-to的主要属性是name,也就是我们把当前根元素重命名的名称。Map-to还有2个属性可以用,分别是ns-uri、ns-prefix。看名称就知道它大概的意识,一个是命名空间的uri另一个则是命名空间的前缀。我们给上面mapping加上这两个属性看看。 结果如下: ~~~ "1.0" encoding="UTF-8"?> "http://hoojo.cnblogs.com" id="1">jackemail 北京"2010-11-22"/> 1#jack#email#北京#2010-11-22 ~~~ 发现了什么?节点元素都带上了ns-prefix的值,而根元素则有了xml的ns。 2、 将一段XML格式字符串转换成JavaBean ~~~ @Test public void readBean4Mapping2XML() { String xml = "" + "jackemail 北京 <生日 birthday=/"2010-11-22/"/>"; try { reader = new StringReader(xml); Unmarshaller unmar = new Unmarshaller(Account.class); unmar.setMapping(mapping); Account account = (Account) unmar.unmarshal(reader); fail(account); } catch (MarshalException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } ~~~ 运行后结果如下: ~~~ 2241#jack#email#北京#2010-11-22 ~~~ 3、 将XML内容解组成Java的Array ~~~ /** * function:将XML内容解组成Java的Array * @author hoojo * @createDate 2011-4-22 下午12:14:50 */ @Test public void array4Mapping2XML() { writer = new StringWriter(); Account[] acc = new Account[2]; acc[0] = bean; bean = new Account(); bean.setName("tom"); bean.setId(223); acc[1] = bean; AccountArray array = new AccountArray(); array.setAccounts(acc); try { Marshaller mar = new Marshaller(writer); mar.setMapping(mapping); mar.marshal(array); fail(writer); reader = new StringReader(writer.toString()); Unmarshaller unmar = new Unmarshaller(AccountArray.class); unmar.setMapping(mapping); array = (AccountArray) unmar.unmarshal(reader); fail(array.getSize()); fail(array.getAccounts()[0]); fail(array.getAccounts()[1]); } catch (MarshalException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } ~~~ AccountArray的mapping配置如下: ~~~ <class name="com.hoo.entity.AccountArray"> <map-to xml="account-array"/> <field name="size" type="int" /> <field name="accounts" collection="array" type="com.hoo.entity.Account"> <bind-xml name="accounts" auto-naming="deriveByClass"/> </field> </class> ~~~ collection表示是数组,auto-maming有2中值,一种是类driverByClass,另一种则是driverByField是属性。 运行后,结果如下: ~~~ "1.0" encoding="UTF-8"?> 2"1">jackemail 北京 <生日 birthday="2010-11-22"/>"223">tom 2 1#jack#email#北京#2010-11-22 223#tom#null#null#null ~~~ 4、 将Map编组、解组成JavaObject ~~~ /** * function:xml转换成Java的Map * @author hoojo * @createDate 2011-4-22 下午12:15:18 */ @Test public void map4Mapping2XML() { writer = new StringWriter(); MapBean mapBean = new MapBean(); Map map = new HashMap(); map.put("No1", bean); bean = new Account(); bean.setName("tom"); bean.setId(223); map.put("No2", bean); mapBean.setMap(map); try { Marshaller mar = new Marshaller(writer); mar.setMapping(mapping); mar.marshal(mapBean); fail(writer); reader = new StringReader(writer.toString()); Unmarshaller unmar = new Unmarshaller(MapBean.class); unmar.setMapping(mapping); mapBean = (MapBean) unmar.unmarshal(reader); fail(mapBean.getMap()); } catch (MarshalException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } ~~~ Mapping配置 ~~~ <class name="com.hoo.entity.MapBean"> <field name="map" collection="map"> <bind-xml name="map"> <class name="org.exolab.castor.mapping.MapItem"> <field name="key" type="java.lang.String"> <bind-xml name="key" node="attribute" /> </field> <field name="value" type="com.hoo.entity.Account"> <bind-xml name="value" auto-naming="deriveByClass"/> </field> </class> </bind-xml> </field> </class> ~~~ 上面的map配置必须这样配置,利用*org.exolab.castor.mapping.MapItem*这个class,完成key、value的配置。 结果如下: ~~~ "1.0" encoding="UTF-8"?> "No2">"223">tom "No1">"1">jackemail 北京 <生日 birthday="2010-11-22"/> {No2=223#tom#null#null#null, No1=1#jack#email#北京#2010-11-22} ~~~ 5、 JavaList编组、解组XML ~~~ /** * function:List到XML的相互转换 * @author hoojo * @createDate 2011-4-22 下午12:16:04 */ @SuppressWarnings("unchecked") @Test public void listForMapping2XML() { writer = new StringWriter(); List list = new ArrayList(); list.add(bean); bean = new Account(); bean.setName("tom"); bean.setId(223); list.add(bean); ListBean listBean = new ListBean(); listBean.setList(list); try { Marshaller mar = new Marshaller(writer); mar.setMapping(mapping); mar.marshal(listBean); fail(writer); reader = new StringReader(writer.toString()); Unmarshaller unmar = new Unmarshaller(ListBean.class); unmar.setMapping(mapping); listBean = (ListBean) unmar.unmarshal(reader); fail(listBean.getList().size()); for (Account acc : (List)listBean.getList()) { fail(acc); } } catch (MarshalException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } ~~~ Mapping配置 ~~~ <class name="com.hoo.entity.ListBean"> <map-to xml="listBean"/> <field name="list" collection="arraylist" type="com.hoo.entity.Account"> <bind-xml name="beans" auto-naming="deriveByClass"/> </field> </class> ~~~ 结果: ~~~ "1.0" encoding="UTF-8"?> "1">jackemail 北京 <生日 birthday="2010-11-22"/>"223">tom 2 1#jack#email#北京#2010-11-22 223#tom#null#null#null ~~~
';

xStream完美转换XML、JSON

最后更新于:2022-04-01 14:22:19

### xStream框架 xStream可以轻易的将Java对象和xml文档相互转换,而且可以修改某个特定的属性和节点名称,而且也支持json的转换; 前面有介绍过json-lib这个框架,在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html](http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html) 以及Jackson这个框架,在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html](http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html) 它们都完美支持JSON,但是对xml的支持还不是很好。一定程度上限制了对Java对象的描述,不能让xml完全体现到对Java对象的描述。这里将会介绍xStream对JSON、XML的完美支持。xStream不仅对XML的转换非常友好,而且提供annotation注解,可以在JavaBean中完成对xml节点、属性的描述。以及对JSON也支持,只需要提供相关的JSONDriver就可以完成转换。 ### 一、准备工作 1、 下载jar包、及官方资源 xStream的jar下载地址: [https://nexus.codehaus.org/content/repositories/releases/com/thoughtworks/xstream/xstream-distribution/1.3.1/xstream-distribution-1.3.1-bin.zip](https://nexus.codehaus.org/content/repositories/releases/com/thoughtworks/xstream/xstream-distribution/1.3.1/xstream-distribution-1.3.1-bin.zip) 官方的示例很全,官方参考示例:[http://xstream.codehaus.org/tutorial.html](http://xstream.codehaus.org/tutorial.html) 添加xstream-1.3.1.jar文件到工程中,就可以开始下面的工作;需要的jar如下: [![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-15_57105c487d84b.gif)](http://hi.csdn.net/attachment/201104/22/0_1303468854S3hL.gif) 2、 测试用例代码 ~~~ package com.hoo.test; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.StringReader; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.codehaus.jettison.json.JSONException; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.hoo.entity.Birthday; import com.hoo.entity.Classes; import com.hoo.entity.ListBean; import com.hoo.entity.Student; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver; import com.thoughtworks.xstream.io.json.JsonWriter; /** * <b>function:</b>Java对象和XML字符串的相互转换 * jar-lib-version: xstream-1.3.1 * @author hoojo * @createDate Nov 27, 2010 12:15:15 PM * @file XStreamTest.java * @package com.hoo.test * @project WebHttpUtils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ @SuppressWarnings("unchecked") public class XStreamTest { private XStream xstream = null; private ObjectOutputStream out = null; private ObjectInputStream in = null; private Student bean = null; /** * <b>function:</b>初始化资源准备 * @author hoojo * @createDate Nov 27, 2010 12:16:28 PM */ @Before public void init() { try { xstream = new XStream(); //xstream = new XStream(new DomDriver()); // 需要xpp3 jar } catch (Exception e) { e.printStackTrace(); } bean = new Student(); bean.setAddress("china"); bean.setEmail("jack@email.com"); bean.setId(1); bean.setName("jack"); Birthday day = new Birthday(); day.setBirthday("2010-11-22"); bean.setBirthday(day); } /** * <b>function:</b>释放对象资源 * @author hoojo * @createDate Nov 27, 2010 12:16:38 PM */ @After public void destory() { xstream = null; bean = null; try { if (out != null) { out.flush(); out.close(); } if (in != null) { in.close(); } } catch (IOException e) { e.printStackTrace(); } System.gc(); } public final void fail(String string) { System.out.println(string); } public final void failRed(String string) { System.err.println(string); } } ~~~ 通过XStream对象的toXML方法就可以完成Java对象到XML的转换,toXML方法还有2个相同签名的方法,需要传递一个流。然后通过流来完成xml信息的输出。 3、 需要的JavaBean ~~~ package com.hoo.entity; public class Student { private int id; private String name; private String email; private String address; private Birthday birthday; //getter、setter public String toString() { return this.name + "#" + this.id + "#" + this.address + "#" + this.birthday + "#" + this.email; } } ~~~ ### 二、Java转换成XML 1、 JavaBean转换XM ~~~ /** * <b>function:</b>Java对象转换成XML字符串 * @author hoojo * @createDate Nov 27, 2010 12:19:01 PM */ @Test public void writeBean2XML() { try { fail("------------Bean->XML------------"); fail(xstream.toXML(bean)); fail("重命名后的XML"); //类重命名 //xstream.alias("account", Student.class); //xstream.alias("生日", Birthday.class); //xstream.aliasField("生日", Student.class, "birthday"); //xstream.aliasField("生日", Birthday.class, "birthday"); //fail(xstream.toXML(bean)); //属性重命名 xstream.aliasField("邮件", Student.class, "email"); //包重命名 xstream.aliasPackage("hoo", "com.hoo.entity"); fail(xstream.toXML(bean)); } catch (Exception e) { e.printStackTrace(); } } ~~~ 看结果中的第一份xml内容,是没有经过然后修改或重命名的文档,按照原样输出。文档中的第二份文档的package经过重命名,email属性也经过重命名以及类名也可以进行重命名的。 运行后结果如下: ~~~ ------------Bean->XML------------ <com.hoo.entity.Student> <id>1</id> <name>jack</name> <email>jack@email.com</email> <address>china</address> <birthday> <birthday>2010-11-22</birthday> </birthday> </com.hoo.entity.Student> ~~~ 重命名后的XML ~~~ <hoo.Student> <id>1</id> <name>jack</name> <邮件>jack@email.com</邮件> <address>china</address> <birthday> <birthday>2010-11-22</birthday> </birthday> </hoo.Student> ~~~ 2、 将List集合转换成xml文档 ~~~ /** * <b>function:</b>将Java的List集合转换成XML对象 * @author hoojo * @createDate Nov 27, 2010 12:20:07 PM */ @Test public void writeList2XML() { try { //修改元素名称 xstream.alias("beans", ListBean.class); xstream.alias("student", Student.class); fail("----------List-->XML----------"); ListBean listBean = new ListBean(); listBean.setName("this is a List Collection"); List<Object> list = new ArrayList<Object>(); list.add(bean); list.add(bean);//引用bean //list.add(listBean);//引用listBean,父元素 bean = new Student(); bean.setAddress("china"); bean.setEmail("tom@125.com"); bean.setId(2); bean.setName("tom"); Birthday day = new Birthday("2010-11-22"); bean.setBirthday(day); list.add(bean); listBean.setList(list); //将ListBean中的集合设置空元素,即不显示集合元素标签 //xstream.addImplicitCollection(ListBean.class, "list"); //设置reference模型 //xstream.setMode(XStream.NO_REFERENCES);//不引用 xstream.setMode(XStream.ID_REFERENCES);//id引用 //xstream.setMode(XStream.XPATH_ABSOLUTE_REFERENCES);//绝对路径引用 //将name设置为父类(Student)的元素的属性 xstream.useAttributeFor(Student.class, "name"); xstream.useAttributeFor(Birthday.class, "birthday"); //修改属性的name xstream.aliasAttribute("姓名", "name"); xstream.aliasField("生日", Birthday.class, "birthday"); fail(xstream.toXML(listBean)); } catch (Exception e) { e.printStackTrace(); } } ~~~ 上面的代码运行后,结果如下: ~~~ ----------List-->XML---------- <beans id="1"> <name>this is a List Collection</name> <list id="2"> <student id="3" 姓名="jack"> <id>1</id> <email>jack@email.com</email> <address>china</address> <birthday id="4" 生日="2010-11-22"/> </student> <student reference="3"/> <student id="5" 姓名="tom"> <id>2</id> <email>tom@125.com</email> <address>china</address> <birthday id="6" 生日="2010-11-22"/> </student> </list> </beans> ~~~ 如果不加xstream.addImplicitCollection(ListBean.**class**, "list"); 这个设置的话,会出现一个List节点包裹着Student节点元素。添加addImplicitCollection可以忽略这个list节点元素。那么上面的list节点就不存在,只会在beans元素中出现name、student这2个xml元素标签; setMode是设置相同的对象的引用方式,如果设置XStream.NO_REFERENCES就是不引用,会输出2分相同的Student元素。如果是XStream.ID_REFERENCES会引用相同的那个对象的id属性,如果是XStream.XPATH_ABSOLUTE_REFERENCES引用,那么它将显示xpath路径。上面采用的id引用,这个引用了id=3的那个student标签元素; useAttributeFor是设置某个节点显示到父节点的属性中,也就是将指定class中的指定属性,在这个class元素节点的属性中显示。 如:hoojo 设置好后就是这样的结果: aliasAttribute是修改属性名称。 3、 在JavaBean中添加Annotation注解进行重命名设置 先看看JavaBean的代码 ~~~ package com.hoo.entity; import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamConverter; import com.thoughtworks.xstream.annotations.XStreamImplicit; import com.thoughtworks.xstream.annotations.XStreamOmitField; @XStreamAlias("class") public class Classes { /* * 设置属性显示 */ @XStreamAsAttribute @XStreamAlias("名称") private String name; /* * 忽略 */ @XStreamOmitField private int number; @XStreamImplicit(itemFieldName = "Students") private List<Student> students; @SuppressWarnings("unused") @XStreamConverter(SingleValueCalendarConverter.class) private Calendar created = new GregorianCalendar(); public Classes(){} public Classes(String name, Student... stu) { this.name = name; this.students = Arrays.asList(stu); } //getter、setter } SingleValueCalendarConverter.java这个是一个类型转换器 package com.hoo.entity; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; public class SingleValueCalendarConverter implements Converter { public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { Calendar calendar = (Calendar) source; writer.setValue(String.valueOf(calendar.getTime().getTime())); } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { GregorianCalendar calendar = new GregorianCalendar(); calendar.setTime(new Date(Long.parseLong(reader.getValue()))); return calendar; } @SuppressWarnings("unchecked") public boolean canConvert(Class type) { return type.equals(GregorianCalendar.class); } } ~~~ 再看看测试用例代码 ~~~ @Test public void writeList2XML4Annotation() { try { failRed("---------annotation Bean --> XML---------"); Student stu = new Student(); stu.setName("jack"); Classes c = new Classes("一班", bean, stu); c.setNumber(2); //对指定的类使用Annotation //xstream.processAnnotations(Classes.class); //启用Annotation //xstream.autodetectAnnotations(true); xstream.alias("student", Student.class); fail(xstream.toXML(c)); } catch (Exception e) { e.printStackTrace(); } } ~~~ 当启用annotation或是对某个特定的类启用annotation时,上面的classes这个类才有效果。如果不启用annotation,运行后结果如下: ~~~ ---------annotation Bean --> XML--------- <com.hoo.entity.Classes> <name>一班</name> <number>2</number> <students class="java.util.Arrays$ArrayList"> <a class="student-array"> <student> <id>1</id> <name>jack</name> <email>jack@email.com</email> <address>china</address> <birthday> <birthday>2010-11-22</birthday> </birthday> </student> <student> <id>0</id> <name>jack</name> </student> </a> </students> <created> <time>1303292056718</time> <timezone>Asia/Shanghai</timezone> </created> </com.hoo.entity.Classes> ~~~ 当启用annotation后xstream.processAnnotations(Classes.class),结果如下: ~~~ ---------annotation Bean --> XML--------- <class 名称="一班"> <Students> <id>1</id> <name>jack</name> <email>jack@email.com</email> <address>china</address> <birthday> <birthday>2010-11-22</birthday> </birthday> </Students> <Students> <id>0</id> <name>jack</name> </Students> <created>1303292242937</created> </class> ~~~ 4、 Map集合转换xml文档 ~~~ /** * <b>function:</b>Java Map集合转XML * @author hoojo * @createDate Nov 27, 2010 1:13:26 PM */ @Test public void writeMap2XML() { try { failRed("---------Map --> XML---------"); Map<String, Student> map = new HashMap<String, Student>(); map.put("No.1", bean);//put bean = new Student(); bean.setAddress("china"); bean.setEmail("tom@125.com"); bean.setId(2); bean.setName("tom"); Birthday day = new Birthday("2010-11-22"); bean.setBirthday(day); map.put("No.2", bean);//put bean = new Student(); bean.setName("jack"); map.put("No.3", bean);//put xstream.alias("student", Student.class); xstream.alias("key", String.class); xstream.useAttributeFor(Student.class, "id"); xstream.useAttributeFor("birthday", String.class); fail(xstream.toXML(map)); } catch (Exception e) { e.printStackTrace(); } } ~~~ 运行后结果如下: ~~~ ---------Map --> XML--------- <map> <entry> <key>No.3</key> <student id="0"> <name>jack</name> </student> </entry> <entry> <key>No.1</key> <student id="1"> <name>jack</name> <email>jack@email.com</email> <address>china</address> <birthday birthday="2010-11-22"/> </student> </entry> <entry> <key>No.2</key> <student id="2"> <name>tom</name> <email>tom@125.com</email> <address>china</address> <birthday birthday="2010-11-22"/> </student> </entry> </map> ~~~ 5、 用OutStream输出流写XML ~~~ /** * <b>function:</b>用OutStream输出流写XML * @author hoojo * @createDate Nov 27, 2010 1:13:48 PM */ @Test public void writeXML4OutStream() { try { out = xstream.createObjectOutputStream(System.out); Student stu = new Student(); stu.setName("jack"); Classes c = new Classes("一班", bean, stu); c.setNumber(2); failRed("---------ObjectOutputStream # JavaObject--> XML---------"); out.writeObject(stu); out.writeObject(new Birthday("2010-05-33")); out.write(22);//byte out.writeBoolean(true); out.writeFloat(22.f); out.writeUTF("hello"); } catch (Exception e) { e.printStackTrace(); } } ~~~ 使用输出流后,可以通过流对象完成xml的构建,即使没有JavaBean对象,你可以用流来构建一个复杂的xml文档,运行后结果如下: ~~~ ---------ObjectOutputStream # JavaObject--> XML--------- <object-stream> <com.hoo.entity.Student> <id>0</id> <name>jack</name> </com.hoo.entity.Student> <com.hoo.entity.Birthday> <birthday>2010-05-33</birthday> </com.hoo.entity.Birthday> <byte>22</byte> <boolean>true</boolean> <float>22.0</float> <string>hello</string> </object-stream> ~~~ 三、### XML内容转换Java对象 1、 用InputStream将XML文档转换成java对象 ~~~ /** * <b>function:</b>用InputStream将XML文档转换成java对象 * 需要额外的jar xpp3-main.jar * @author hoojo * @createDate Nov 27, 2010 1:14:52 PM */ @Test public void readXML4InputStream() { try { String s = "<object-stream><com.hoo.entity.Student><id>0</id><name>jack</name>" + "</com.hoo.entity.Student><com.hoo.entity.Birthday><birthday>2010-05-33</birthday>" + "</com.hoo.entity.Birthday><byte>22</byte><boolean>true</boolean><float>22.0</float>" + "<string>hello</string></object-stream>"; failRed("---------ObjectInputStream## XML --> javaObject---------"); StringReader reader = new StringReader(s); in = xstream.createObjectInputStream(reader); Student stu = (Student) in.readObject(); Birthday b = (Birthday) in.readObject(); byte i = in.readByte(); boolean bo = in.readBoolean(); float f = in.readFloat(); String str = in.readUTF(); System.out.println(stu); System.out.println(b); System.out.println(i); System.out.println(bo); System.out.println(f); System.out.println(str); } catch (Exception e) { e.printStackTrace(); } } ~~~ 读取后,转换的Java对象,结果如下: ~~~ ---------ObjectInputStream## XML --> javaObject--------- jack#0#null#null#null 2010-05-33 22 true 22.0 hello ~~~ 2、 将xml文档转换成Java对象 ~~~ /** * <b>function:</b>将XML字符串转换成Java对象 * @author hoojo * @createDate Nov 27, 2010 2:39:06 PM */ @Test public void readXml2Object() { try { failRed("-----------Xml >>> Bean--------------"); Student stu = (Student) xstream.fromXML(xstream.toXML(bean)); fail(stu.toString()); List<Student> list = new ArrayList<Student>(); list.add(bean);//add Map<String, Student> map = new HashMap<String, Student>(); map.put("No.1", bean);//put bean = new Student(); bean.setAddress("china"); bean.setEmail("tom@125.com"); bean.setId(2); bean.setName("tom"); Birthday day = new Birthday("2010-11-22"); bean.setBirthday(day); list.add(bean);//add map.put("No.2", bean);//put bean = new Student(); bean.setName("jack"); list.add(bean);//add map.put("No.3", bean);//put failRed("==========XML >>> List==========="); List<Student> studetns = (List<Student>) xstream.fromXML(xstream.toXML(list)); fail("size:" + studetns.size());//3 for (Student s : studetns) { fail(s.toString()); } failRed("==========XML >>> Map==========="); Map<String, Student> maps = (Map<String, Student>) xstream.fromXML(xstream.toXML(map)); fail("size:" + maps.size());//3 Set<String> key = maps.keySet(); Iterator<String> iter = key.iterator(); while (iter.hasNext()) { String k = iter.next(); fail(k + ":" + map.get(k)); } } catch (Exception e) { e.printStackTrace(); } } ~~~ 运行后结果如下: ~~~ -----------Xml >>> Bean-------------- jack#1#china#2010-11-22#jack@email.com ==========XML >>> List=========== size:3 jack#1#china#2010-11-22#jack@email.com tom#2#china#2010-11-22#tom@125.com jack#0#null#null#null ==========XML >>> Map=========== size:3 No.3:jack#0#null#null#null No.1:jack#1#china#2010-11-22#jack@email.com No.2:tom#2#china#2010-11-22#tom@125.com ~~~ 怎么样,成功的完成XML到JavaBean、List、Map的转换,更多对象转换还需要大家一一尝试。用法类似~这里就不一样赘述。 ### 四、XStream对JSON的支持 xStream对JSON也有非常好的支持,它提供了2个模型驱动。用这2个驱动可以完成Java对象到JSON的相互转换。使用JettisonMappedXmlDriver驱动,将Java对象转换成json,需要添加jettison.jar 1、 用JettisonMappedXmlDriver完成Java对象到JSON的转换 ~~~ /** * <b>function:</b>XStream结合JettisonMappedXmlDriver驱动,转换Java对象到JSON * 需要添加jettison jar * @author hoojo * @createDate Nov 27, 2010 1:23:18 PM */ @Test public void writeEntity2JETTSON() { failRed("=======JettisonMappedXmlDriver===JavaObject >>>> JaonString========="); xstream = new XStream(new JettisonMappedXmlDriver()); xstream.setMode(XStream.NO_REFERENCES); xstream.alias("student", Student.class); fail(xstream.toXML(bean)); } ~~~ 运行后结果如下: ~~~ =======JettisonMappedXmlDriver===JavaObject >>>> JaonString========= {"student":{"id":1,"name":"jack","email":"jack@email.com","address":"china","birthday":[{},"2010-11-22"]}} ~~~ JSON的转换和XML的转换用法一样,只是创建XStream需要传递一个参数,这个参数就是xml到JSON映射转换的驱动。这里会降到两个驱动,分别是JettisonMappedXmlDriver、JsonHierarchicalStreamDriver。 2、 JsonHierarchicalStreamDriver完成Java对象到JSON的转换 ~~~ /** * <b>function:</b>用XStream结合JsonHierarchicalStreamDriver驱动 * 转换java对象为JSON字符串 * @author hoojo * @createDate Nov 27, 2010 1:16:46 PM */ @Test public void writeEntiry2JSON() { failRed("======JsonHierarchicalStreamDriver====JavaObject >>>> JaonString========="); xstream = new XStream(new JsonHierarchicalStreamDriver()); //xstream.setMode(XStream.NO_REFERENCES); xstream.alias("student", Student.class); failRed("-------Object >>>> JSON---------"); fail(xstream.toXML(bean)); //failRed("========JsonHierarchicalStreamDriver==删除根节点========="); //删除根节点 xstream = new XStream(new JsonHierarchicalStreamDriver() { public HierarchicalStreamWriter createWriter(Writer out) { return new JsonWriter(out, JsonWriter.DROP_ROOT_MODE); } }); //xstream.setMode(XStream.NO_REFERENCES); xstream.alias("student", Student.class); fail(xstream.toXML(bean)); } ~~~ 运行后结果如下: ~~~ ======JsonHierarchicalStreamDriver====JavaObject >>>> JaonString========= -------Object >>>> JSON--------- {"student": { "id": 1, "name": "jack", "email": "jack@email.com", "address": "china", "birthday": { "birthday": "2010-11-22" } }} { "id": 1, "name": "jack", "email": "jack@email.com", "address": "china", "birthday": { "birthday": "2010-11-22" } } ~~~ 使用JsonHierarchicalStreamDriver转换默认会给转换后的对象添加一个根节点,但是在构建JsonHierarchicalStreamDriver驱动的时候,你可以重写createWriter方法,删掉根节点。 看上面的结果,一个是默认带根节点的JSON对象,它只是将类名作为一个属性,将对象作为该属性的一个值。而另一个没有带根属性的JSON就是通过重写createWriter方法完成的。 3、 将List集合转换成JSON字符串 ~~~ @Test public void writeList2JSON() { failRed("======JsonHierarchicalStreamDriver====JavaObject >>>> JaonString========="); JsonHierarchicalStreamDriver driver = new JsonHierarchicalStreamDriver(); xstream = new XStream(driver); //xstream = new XStream(new JettisonMappedXmlDriver());//转换错误 //xstream.setMode(XStream.NO_REFERENCES); xstream.alias("student", Student.class); List<Student> list = new ArrayList<Student>(); list.add(bean);//add bean = new Student(); bean.setAddress("china"); bean.setEmail("tom@125.com"); bean.setId(2); bean.setName("tom"); Birthday day = new Birthday("2010-11-22"); bean.setBirthday(day); list.add(bean);//add bean = new Student(); bean.setName("jack"); list.add(bean);//add fail(xstream.toXML(list)); //failRed("========JsonHierarchicalStreamDriver==删除根节点========="); //删除根节点 xstream = new XStream(new JsonHierarchicalStreamDriver() { public HierarchicalStreamWriter createWriter(Writer out) { return new JsonWriter(out, JsonWriter.DROP_ROOT_MODE); } }); xstream.alias("student", Student.class); fail(xstream.toXML(list)); } ~~~ 运行后结果如下 ~~~ ======JsonHierarchicalStreamDriver====JavaObject >>>> JaonString========= ##{"list": [ { "id": 1, "name": "jack", "email": "jack@email.com", "address": "china", "birthday": { "birthday": "2010-11-22" } }, { "id": 2, "name": "tom", "email": "tom@125.com", "address": "china", "birthday": { "birthday": "2010-11-22" } }, { "id": 0, "name": "jack" } ]} #[ { "id": 1, "name": "jack", "email": "jack@email.com", "address": "china", "birthday": { "birthday": "2010-11-22" } }, { "id": 2, "name": "tom", "email": "tom@125.com", "address": "china", "birthday": { "birthday": "2010-11-22" } }, { "id": 0, "name": "jack" } ] ~~~ 上面的list1是使用JsonHierarchicalStreamDriver 转换的,当然你也可以使用JettisonMappedXmlDriver驱动进行转换;用JettisonMappedXmlDriver转换后,你会发现格式不同而且没有根属性。 4、 Map转换json ~~~ @Test public void writeMap2JSON() { failRed("======JsonHierarchicalStreamDriver==== Map >>>> JaonString========="); xstream = new XStream(new JsonHierarchicalStreamDriver()); //xstream = new XStream(new JettisonMappedXmlDriver()); xstream.alias("student", Student.class); Map<String, Student> map = new HashMap<String, Student>(); map.put("No.1", bean);//put bean = new Student(); bean.setAddress("china"); bean.setEmail("tom@125.com"); bean.setId(2); bean.setName("tom"); bean.setBirthday(new Birthday("2010-11-21")); map.put("No.2", bean);//put bean = new Student(); bean.setName("jack"); map.put("No.3", bean);//put fail(xstream.toXML(map)); //failRed("========JsonHierarchicalStreamDriver==删除根节点========="); //删除根节点 xstream = new XStream(new JsonHierarchicalStreamDriver() { public HierarchicalStreamWriter createWriter(Writer out) { return new JsonWriter(out, JsonWriter.DROP_ROOT_MODE); } }); xstream.alias("student", Student.class); fail(xstream.toXML(map)); } ~~~ 运行后结果如下: ~~~ ======JsonHierarchicalStreamDriver==== Map >>>> JaonString========= {"map": [ [ "No.3", { "id": 0, "name": "jack" } ], [ "No.1", { "id": 1, "name": "jack", "email": "jack@email.com", "address": "china", "birthday": { "birthday": "2010-11-22" } } ], [ "No.2", { "id": 2, "name": "tom", "email": "tom@125.com", "address": "china", "birthday": { "birthday": "2010-11-21" } } ] ]} [ [ "No.3", { "id": 0, "name": "jack" } ], [ "No.1", { "id": 1, "name": "jack", "email": "jack@email.com", "address": "china", "birthday": { "birthday": "2010-11-22" } } ], [ "No.2", { "id": 2, "name": "tom", "email": "tom@125.com", "address": "china", "birthday": { "birthday": "2010-11-21" } } ] ] ~~~ 5、 将JSON转换java对象 ~~~ /** * <b>function:</b>JsonHierarchicalStreamDriver可以将简单的json字符串转换成java对象,list、map转换不成功; * JsonHierarchicalStreamDriver读取JSON字符串到java对象出错 * @author hoojo * @createDate Nov 27, 2010 1:22:26 PM * @throws JSONException */ @Test public void readJSON2Object() throws JSONException { String json = "{/"student/": {" + "/"id/": 1," + "/"name/": /"haha/"," + "/"email/": /"email/"," + "/"address/": /"address/"," + "/"birthday/": {" + "/"birthday/": /"2010-11-22/"" + "}" + "}}"; //JsonHierarchicalStreamDriver读取JSON字符串到java对象出错,但JettisonMappedXmlDriver可以 xstream = new XStream(new JettisonMappedXmlDriver()); xstream.alias("student", Student.class); fail(xstream.fromXML(json).toString()); //JettisonMappedXmlDriver转换List集合出错,但JsonHierarchicalStreamDriver可以转换正确 //JettisonMappedXmlDriver 转换的字符串 {"list":{"student":[{"id":1,"name":"haha","email":"email","address":"address","birthday":[{},"2010-11-22"]}]},"student":{"id":2,"name":"tom","email":"tom@125.com","address":"china","birthday":[{},"2010-11-22"]}} json = "{/"list/": [{" + "/"id/": 1," + "/"name/": /"haha/"," + "/"email/": /"email/"," + "/"address/": /"address/"," + "/"birthday/": {" + "/"birthday/": /"2010-11-22/"" + "}" + "},{" + "/"id/": 2," + "/"name/": /"tom/"," + "/"email/": /"tom@125.com/"," + "/"address/": /"china/"," + "/"birthday/": {" + "/"birthday/": /"2010-11-22/"" + "}" + "}]}"; System.out.println(json);//用js转换成功 List list = (List) xstream.fromXML(json); System.out.println(list.size());//0好像转换失败 } ~~~ 运行后结果如下: ~~~ haha#1#address#2010-11-22#email {"list": [{"id": 1,"name": "haha","email": "email","address": "address","birthday": {"birthday": "2010-11-22"}}, {"id": 2,"name": "tom","email": "tom@125.com","address": "china","birthday": {"birthday": "2010-11-22"}}]} 0 ~~~ JSON到Java的转换是fromXML方法。
';

Jackson 框架,轻易转换JSON

最后更新于:2022-04-01 14:22:16

Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。 前面有介绍过json-lib这个框架,在线博文:[http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html](http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html) 相比json-lib框架,Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。而且Jackson社区相对比较活跃,更新速度也比较快。 ### 一、准备工作 1、 下载依赖库jar包 Jackson的jar all下载地址:[http://jackson.codehaus.org/1.7.6/jackson-all-1.7.6.jar](http://jackson.codehaus.org/1.7.6/jackson-all-1.7.6.jar) 然后在工程中导入这个jar包即可开始工作 官方示例:[http://wiki.fasterxml.com/JacksonInFiveMinutes](http://wiki.fasterxml.com/JacksonInFiveMinutes) 因为下面的程序是用junit测试用例运行的,所以还得添加junit的jar包。版本是junit-4.2.8 如果你需要转换xml,那么还需要stax2-api.jar 2、 测试类基本代码如下 ~~~ package com.hoo.test; import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.codehaus.jackson.JsonEncoding; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.node.JsonNodeFactory; import org.codehaus.jackson.xml.XmlMapper; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.hoo.entity.AccountBean; /** * function:Jackson 将java对象转换成JSON字符串,也可以将JSON字符串转换成java对象 * jar-lib-version: jackson-all-1.6.2 * jettison-1.0.1 * @author hoojo * @createDate 2010-11-23 下午04:54:53 * @file JacksonTest.java * @package com.hoo.test * @project Spring3 * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ @SuppressWarnings("unchecked") public class JacksonTest { private JsonGenerator jsonGenerator = null; private ObjectMapper objectMapper = null; private AccountBean bean = null; @Before public void init() { bean = new AccountBean(); bean.setAddress("china-Guangzhou"); bean.setEmail("hoojo_@126.com"); bean.setId(1); bean.setName("hoojo"); objectMapper = new ObjectMapper(); try { jsonGenerator = objectMapper.getJsonFactory().createJsonGenerator(System.out, JsonEncoding.UTF8); } catch (IOException e) { e.printStackTrace(); } } @After public void destory() { try { if (jsonGenerator != null) { jsonGenerator.flush(); } if (!jsonGenerator.isClosed()) { jsonGenerator.close(); } jsonGenerator = null; objectMapper = null; bean = null; System.gc(); } catch (IOException e) { e.printStackTrace(); } } } ~~~ 3、 所需要的JavaEntity ~~~ package com.hoo.entity; public class AccountBean { private int id; private String name; private String email; private String address; private Birthday birthday; //getter、setter @Override public String toString() { return this.name + "#" + this.id + "#" + this.address + "#" + this.birthday + "#" + this.email; } } Birthday package com.hoo.entity; public class Birthday { private String birthday; public Birthday(String birthday) { super(); this.birthday = birthday; } //getter、setter public Birthday() {} @Override public String toString() { return this.birthday; } } ~~~ ### 二、Java对象转换成JSON 1、 JavaBean(Entity/Model)转换成JSON ~~~ /** * function:将java对象转换成json字符串 * @author hoojo * @createDate 2010-11-23 下午06:01:10 */ @Test public void writeEntityJSON() { try { System.out.println("jsonGenerator"); //writeObject可以转换java对象,eg:JavaBean/Map/List/Array等 jsonGenerator.writeObject(bean); System.out.println(); System.out.println("ObjectMapper"); //writeValue具有和writeObject相同的功能 objectMapper.writeValue(System.out, bean); } catch (IOException e) { e.printStackTrace(); } } ~~~ 运行后结果如下: ~~~ jsonGenerator {"address":"china-Guangzhou","name":"hoojo","id":1,"birthday":null,"email":"hoojo_@126.com"} ObjectMapper {"address":"china-Guangzhou","name":"hoojo","id":1,"birthday":null,"email":"hoojo_@126.com"} ~~~ 上面分别利用JsonGenerator的writeObject方法和ObjectMapper的writeValue方法完成对Java对象的转换,二者传递的参数及构造的方式不同;JsonGenerator的创建依赖于ObjectMapper对象。也就是说如果你要使用JsonGenerator来转换JSON,那么你必须创建一个ObjectMapper。但是你用ObjectMapper来转换JSON,则不需要JSONGenerator。 objectMapper的writeValue方法可以将一个Java对象转换成JSON。这个方法的参数一,需要提供一个输出流,转换后可以通过这个流来输出转换后的内容。或是提供一个File,将转换后的内容写入到File中。当然,这个参数也可以接收一个JSONGenerator,然后通过JSONGenerator来输出转换后的信息。第二个参数是将要被转换的Java对象。如果用三个参数的方法,那么是一个Config。这个config可以提供一些转换时的规则,过指定的Java对象的某些属性进行过滤或转换等。 2、 将Map集合转换成Json字符串 ~~~ /** * function:将map转换成json字符串 * @author hoojo * @createDate 2010-11-23 下午06:05:26 */ @Test public void writeMapJSON() { try { Map map = new HashMap(); map.put("name", bean.getName()); map.put("account", bean); bean = new AccountBean(); bean.setAddress("china-Beijin"); bean.setEmail("hoojo@qq.com"); map.put("account2", bean); System.out.println("jsonGenerator"); jsonGenerator.writeObject(map); System.out.println(""); System.out.println("objectMapper"); objectMapper.writeValue(System.out, map); } catch (IOException e) { e.printStackTrace(); } } ~~~ 转换后结果如下: ~~~ jsonGenerator {"account2":{"address":"china-Beijin","name":null,"id":0,"birthday":null,"email":"hoojo@qq.com"},"name":"hoojo", "account":{"address":"china-Guangzhou","name":"hoojo","id":1,"birthday":null,"email":"hoojo_@126.com"}} objectMapper {"account2":{"address":"china-Beijin","name":null,"id":0,"birthday":null,"email":"hoojo@qq.com"},"name":"hoojo", "account":{"address":"china-Guangzhou","name":"hoojo","id":1,"birthday":null,"email":"hoojo_@126.com"}} ~~~ 3、 将List集合转换成json ~~~ /** * function:将list集合转换成json字符串 * @author hoojo * @createDate 2010-11-23 下午06:05:59 */ @Test public void writeListJSON() { try { List list = new ArrayList(); list.add(bean); bean = new AccountBean(); bean.setId(2); bean.setAddress("address2"); bean.setEmail("email2"); bean.setName("haha2"); list.add(bean); System.out.println("jsonGenerator"); //list转换成JSON字符串 jsonGenerator.writeObject(list); System.out.println(); System.out.println("ObjectMapper"); //用objectMapper直接返回list转换成的JSON字符串 System.out.println("1###" + objectMapper.writeValueAsString(list)); System.out.print("2###"); //objectMapper list转换成JSON字符串 objectMapper.writeValue(System.out, list); } catch (IOException e) { e.printStackTrace(); } } ~~~ 结果如下: ~~~ jsonGenerator [{"address":"china-Guangzhou","name":"hoojo","id":1,"birthday":null,"email":"hoojo_@126.com"}, {"address":"address2","name":"haha2","id":2,"birthday":null,"email":"email2"}] ObjectMapper 1###[{"address":"china-Guangzhou","name":"hoojo","id":1,"birthday":null,"email":"hoojo_@126.com"}, {"address":"address2","name":"haha2","id":2,"birthday":null,"email":"email2"}] 2###[{"address":"china-Guangzhou","name":"hoojo","id":1,"birthday":null,"email":"hoojo_@126.com"}, {"address":"address2","name":"haha2","id":2,"birthday":null,"email":"email2"}] ~~~ 外面就是多了个[]中括号;同样Array也可以转换,转换的JSON和上面的结果是一样的,这里就不再转换了。~.~ 4、下面来看看jackson提供的一些类型,用这些类型完成json转换;如果你使用这些类型转换JSON的话,那么你即使没有JavaBean(Entity)也可以完成复杂的Java类型的JSON转换。下面用到这些类型构建一个复杂的Java对象,并完成JSON转换。 ~~~ public void writeOthersJSON() { try { String[] arr = { "a", "b", "c" }; System.out.println("jsonGenerator"); String str = "hello world jackson!"; //byte jsonGenerator.writeBinary(str.getBytes()); //boolean jsonGenerator.writeBoolean(true); //null jsonGenerator.writeNull(); //float jsonGenerator.writeNumber(2.2f); //char jsonGenerator.writeRaw("c"); //String jsonGenerator.writeRaw(str, 5, 10); //String jsonGenerator.writeRawValue(str, 5, 5); //String jsonGenerator.writeString(str); jsonGenerator.writeTree(JsonNodeFactory.instance.POJONode(str)); System.out.println(); //Object jsonGenerator.writeStartObject();//{ jsonGenerator.writeObjectFieldStart("user");//user:{ jsonGenerator.writeStringField("name", "jackson");//name:jackson jsonGenerator.writeBooleanField("sex", true);//sex:true jsonGenerator.writeNumberField("age", 22);//age:22 jsonGenerator.writeEndObject();//} jsonGenerator.writeArrayFieldStart("infos");//infos:[ jsonGenerator.writeNumber(22);//22 jsonGenerator.writeString("this is array");//this is array jsonGenerator.writeEndArray();//] jsonGenerator.writeEndObject();//} AccountBean bean = new AccountBean(); bean.setAddress("address"); bean.setEmail("email"); bean.setId(1); bean.setName("haha"); //complex Object jsonGenerator.writeStartObject();//{ jsonGenerator.writeObjectField("user", bean);//user:{bean} jsonGenerator.writeObjectField("infos", arr);//infos:[array] jsonGenerator.writeEndObject();//} } catch (Exception e) { e.printStackTrace(); } } ~~~ 运行后,结果如下: ~~~ jsonGenerator "aGVsbG8gd29ybGQgamFja3NvbiE=" true null 2.2c world jac worl "hello world jackson!" "hello world jackson!" {"user":{"name":"jackson","sex":true,"age":22},"infos":[22,"this is array"]} {"user":{"address":"address","name":"haha","id":1,"birthday":null,"email":"email"},"infos":["a","b","c"]} ~~~ 怎么样?构造的json字符串和输出的结果是一致的吧。关键看懂用JSONGenerator提供的方法,完成一个Object的构建。 ### 三、JSON转换成Java对象 1、 将json字符串转换成JavaBean对象 ~~~ @Test public void readJson2Entity() { String json = "{/"address/":/"address/",/"name/":/"haha/",/"id/":1,/"email/":/"email/"}"; try { AccountBean acc = objectMapper.readValue(json, AccountBean.class); System.out.println(acc.getName()); System.out.println(acc); } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } ~~~ 很简单,用到了ObjectMapper这个对象的readValue这个方法,这个方法需要提供2个参数。第一个参数就是解析的JSON字符串,第二个参数是即将将这个JSON解析吃什么Java对象,Java对象的类型。当然,还有其他相同签名方法,如果你有兴趣可以一一尝试使用方法,当然使用的方法和当前使用的方法大同小异。运行后,结果如下: ~~~ haha haha#1#address#null#email ~~~ 2、 将json字符串转换成List集合 ~~~ /** * function:json字符串转换成list * @author hoojo * @createDate 2010-11-23 下午06:12:01 */ @Test public void readJson2List() { String json = "[{/"address/": /"address2/",/"name/":/"haha2/",/"id/":2,/"email/":/"email2/"},"+ "{/"address/":/"address/",/"name/":/"haha/",/"id/":1,/"email/":/"email/"}]"; try { List> list = objectMapper.readValue(json, List.class); System.out.println(list.size()); for (int i = 0; i < list.size(); i++) { Map map = list.get(i); Set set = map.keySet(); for (Iterator it = set.iterator();it.hasNext();) { String key = it.next(); System.out.println(key + ":" + map.get(key)); } } } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } ~~~ 尝试过将上面的JSON转换成List,然后List中存放AccountBean,但结果失败了。但是支持Map集合。因为你转成List.class,但是不知道List存放何种类型。只好默然Map类型。因为所有的对象都可以转换成Map结合,运行后结果如下: ~~~ 2 address:address2 name:haha2 id:2 email:email2 address:address name:haha id:1 email:email ~~~ 3、 Json字符串转换成Array数组,由于上面的泛型转换不能识别到集合中的对象类型。所有这里用对象数组,可以解决这个问题。只不过它不再是集合,而是一个数组。当然这个不重要,你可以用Arrays.asList将其转换成List即可。 ~~~ /** * function:json字符串转换成Array * @author hoojo * @createDate 2010-11-23 下午06:14:01 */ @Test public void readJson2Array() { String json = "[{/"address/": /"address2/",/"name/":/"haha2/",/"id/":2,/"email/":/"email2/"},"+ "{/"address/":/"address/",/"name/":/"haha/",/"id/":1,/"email/":/"email/"}]"; try { AccountBean[] arr = objectMapper.readValue(json, AccountBean[].class); System.out.println(arr.length); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } ~~~ 运行后的结果: ~~~ 2 haha2#2#address2#null#email2 haha#1#address#null#email ~~~ 4、 Json字符串转换成Map集合 ~~~ /** * function:json字符串转换Map集合 * @author hoojo * @createDate Nov 27, 2010 3:00:06 PM */ @Test public void readJson2Map() { String json = "{/"success/":true,/"A/":{/"address/": /"address2/",/"name/":/"haha2/",/"id/":2,/"email/":/"email2/"},"+ "/"B/":{/"address/":/"address/",/"name/":/"haha/",/"id/":1,/"email/":/"email/"}}"; try { Map> maps = objectMapper.readValue(json, Map.class); System.out.println(maps.size()); Set key = maps.keySet(); Iterator iter = key.iterator(); while (iter.hasNext()) { String field = iter.next(); System.out.println(field + ":" + maps.get(field)); } } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } ~~~ 运行后结果如下: ~~~ 3 success:true A:{address=address2, name=haha2, id=2, email=email2} B:{address=address, name=haha, id=1, email=email} ~~~ ### 四、Jackson对XML的支持 Jackson也可以完成java对象到xml的转换,转换后的结果要比json-lib更直观,不过它依赖于stax2-api.jar这个jar包。 ~~~ /** * function:java对象转换成xml文档 * 需要额外的jar包 stax2-api.jar * @author hoojo * @createDate 2010-11-23 下午06:11:21 */ @Test public void writeObject2Xml() { //stax2-api-3.0.2.jar System.out.println("XmlMapper"); XmlMapper xml = new XmlMapper(); try { //javaBean转换成xml //xml.writeValue(System.out, bean); StringWriter sw = new StringWriter(); xml.writeValue(sw, bean); System.out.println(sw.toString()); //List转换成xml List list = new ArrayList(); list.add(bean); list.add(bean); System.out.println(xml.writeValueAsString(list)); //Map转换xml文档 Map map = new HashMap(); map.put("A", bean); map.put("B", bean); System.out.println(xml.writeValueAsString(map)); } catch (JsonGenerationException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } ~~~ 运行上面的方法,结果如下: ~~~ XmlMapper <unknown><address>china-Guangzhouaddress><name>hoojoname><id>1id><birthday/><email>hoojo_@126.comemail>unknown> <unknown><unknown><address>china-Guangzhouaddress><name>hoojoname><id>1id><birthday/><email>hoojo_@126.comemail>unknown> <email><address>china-Guangzhouaddress><name>hoojoname><id>1id><birthday/><email>hoojo_@126.comemail>email>unknown> <unknown><A><address>china-Guangzhouaddress><name>hoojoname><id>1id><birthday/><email>hoojo_@126.comemail>A> <B><address>china-Guangzhouaddress><name>hoojoname><id>1id><birthday/><email>hoojo_@126.comemail>B>unknown> ~~~ 看结果,根节点都是unknown 这个问题还没有解决,由于根节点没有转换出来,所有导致解析xml到Java对象,也无法完成。
';

JSON-lib框架,转换JSON、XML不再困难

最后更新于:2022-04-01 14:22:14

Json-lib可以将Java对象转成json格式的字符串,也可以将Java对象转换成xml格式的文档,同样可以将json字符串转换成Java对象或是将xml字符串转换成Java对象。 ### 一、准备工作 1、 首先要去官方下载json-lib工具包 下载地址: [http://sourceforge.net/projects/json-lib/files/json-lib/json-lib-2.4/](http://sourceforge.net/projects/json-lib/files/json-lib/json-lib-2.4/) 目前最新的是2.4的版本,本示例中使用的是v2.3;json-lib还需要以下依赖包: jakarta commons-lang 2.5 jakarta commons-beanutils 1.8.0 jakarta commons-collections 3.2.1 jakarta commons-logging 1.1.1 ezmorph 1.0.6 官方网址:[http://json-lib.sourceforge.net/](http://json-lib.sourceforge.net/) 然后在工程中添加如下jar包: [![clip_image002](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-15_57105c4860aa6.gif "clip_image002")](http://hi.csdn.net/attachment/201104/21/0_1303377455oubU.gif) 当然你也可以用2.4的json-lib库 你可以在这里看看官方提供的示例: [http://json-lib.sourceforge.net/usage.html](http://json-lib.sourceforge.net/usage.html) 由于本次介绍的示例需要junit工具,所以你还需要添加junit的jar文件,版本是4.8.2版本的,下载地址:[https://github.com/KentBeck/junit/downloads](https://github.com/KentBeck/junit/downloads) 如果你还不了解JSON是什么?那么你应该可以看看[http://www.json.org/json-zh.html](http://www.json.org/json-zh.html) 2、 要转换的JavaBean的代码如下: ~~~ package com.hoo.entity; public class Student { private int id; private String name; private String email; private String address; private Birthday birthday; //setter、getter public String toString() { return this.name + "#" + this.id + "#" + this.address + "#" + this.birthday + "#" + this.email; } } Birthday.java package com.hoo.entity; public class Birthday { private String birthday; public Birthday(String birthday) { super(); this.birthday = birthday; } //setter、getter public Birthday() {} @Override public String toString() { return this.birthday; } } ~~~ 注意,上面的getter、setter方法省略了,自己构建下。 3、 新建JsonlibTest测试类,基本代码如下: ~~~ package com.hoo.test; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONFunction; import net.sf.json.JSONObject; import net.sf.json.JSONSerializer; import net.sf.json.JsonConfig; import net.sf.json.processors.JsonValueProcessor; import net.sf.json.util.PropertyFilter; import net.sf.json.xml.XMLSerializer; import org.apache.commons.beanutils.PropertyUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.hoo.entity.Birthday; import com.hoo.entity.Student; /** * <b>function:</b> 用json-lib转换java对象到JSON字符串 * 读取json字符串到java对象,序列化jsonObject到xml * json-lib-version: json-lib-2.3-jdk15.jar * 依赖包: * commons-beanutils.jar * commons-collections-3.2.jar * ezmorph-1.0.3.jar * commons-lang.jar * commons-logging.jar * @author hoojo * @createDate Nov 28, 2010 2:28:39 PM * @file JsonlibTest.java * @package com.hoo.test * @project WebHttpUtils * @blog http://blog.csdn.net/IBM_hoojo * @email hoojo_@126.com * @version 1.0 */ @SuppressWarnings({ "deprecation", "unchecked" }) public class JsonlibTest { private JSONArray jsonArray = null; private JSONObject jsonObject = null; private Student bean = null; @Before public void init() { jsonArray = new JSONArray(); jsonObject = new JSONObject(); bean = new Student(); bean.setAddress("address"); bean.setEmail("email"); bean.setId(1); bean.setName("haha"); Birthday day = new Birthday(); day.setBirthday("2010-11-22"); bean.setBirthday(day); } @After public void destory() { jsonArray = null; jsonObject = null; bean = null; System.gc(); } public final void fail(String string) { System.out.println(string); } public final void failRed(String string) { System.err.println(string); } } ~~~ 上面的init会在每个方法之前运行,destory会在每个方法完成后执行。分别用到了junit的@Before、@After注解,如果你对junit的这些注解不是很了解,可以看看junit官方的测试用例的example和doc; JSONObject是将Java对象转换成一个json的Object形式,JSONArray是将一个Java对象转换成json的Array格式。 那什么是json的Object形式、Array形式? 用通俗易懂的方法将,所谓的json的Object形式就是一个花括号里面存放的如JavaMap的键值对,如:{name:’hoojo’, age: 24}; 那么json的Array形式呢? 就是中括号,括起来的数组。如:[ ‘json’, true, 22]; 如果你还想了解更多json方面的知识,请看:[http://www.json.org/json-zh.html](http://www.json.org/json-zh.html) 除了上面的JSONArray、JSONObject可以将Java对象转换成JSON或是相反,将JSON字符串转换成Java对象,还有一个对象也可以完成上面的功能,它就是JSONSerializer;下面我们就来看看它们是怎么玩转Java对象和JSON的。 ### 二、Java对象序列化成JSON对象 1、 将JavaObject转换吃JSON字符串 在JsonlibTest中添加如下代码: ~~~ /*=========================Java Object >>>> JSON String ===========================*/ /** * <b>function:</b>转Java Bean对象到JSON * @author hoojo * @createDate Nov 28, 2010 2:35:54 PM */ @Test public void writeEntity2JSON() { fail("==============Java Bean >>> JSON Object=================="); fail(JSONObject.fromObject(bean).toString()); fail("==============Java Bean >>> JSON Array=================="); fail(JSONArray.fromObject(bean).toString());//array会在最外层套上[] fail("==============Java Bean >>> JSON Object =================="); fail(JSONSerializer.toJSON(bean).toString()); fail("========================JsonConfig========================"); JsonConfig jsonConfig = new JsonConfig(); jsonConfig.registerJsonValueProcessor(Birthday.class, new JsonValueProcessor() { public Object processArrayValue(Object value, JsonConfig jsonConfig) { if (value == null) { return new Date(); } return value; } public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) { fail("key:" + key); return value + "##修改过的日期"; } }); jsonObject = JSONObject.fromObject(bean, jsonConfig); fail(jsonObject.toString()); Student student = (Student) JSONObject.toBean(jsonObject, Student.class); fail(jsonObject.getString("birthday")); fail(student.toString()); fail("#####################JsonPropertyFilter############################"); jsonConfig.setJsonPropertyFilter(new PropertyFilter() { public boolean apply(Object source, String name, Object value) { fail(source + "%%%" + name + "--" + value); //忽略birthday属性 if (value != null && Birthday.class.isAssignableFrom(value.getClass())) { return true; } return false; } }); fail(JSONObject.fromObject(bean, jsonConfig).toString()); fail("#################JavaPropertyFilter##################"); jsonConfig.setRootClass(Student.class); jsonConfig.setJavaPropertyFilter(new PropertyFilter() { public boolean apply(Object source, String name, Object value) { fail(name + "@" + value + "#" + source); if ("id".equals(name) || "email".equals(name)) { value = name + "@@"; return true; } return false; } }); //jsonObject = JSONObject.fromObject(bean, jsonConfig); //student = (Student) JSONObject.toBean(jsonObject, Student.class); //fail(student.toString()); student = (Student) JSONObject.toBean(jsonObject, jsonConfig); fail("Student:" + student.toString()); } ~~~ fromObject将Java对象转换成json字符串,toBean将json对象转换成Java对象; 上面方法值得注意的是使用了JsonConfig这个对象,这个对象可以在序列化的时候对JavaObject的数据进行处理、过滤等 上面的jsonConfig的registerJsonValueProcessor方法可以完成对象值的处理和修改,比如处理生日为null时,给一个特定的值。同样setJsonPropertyFilter和setJavaPropertyFilter都是完成对转换后的值的处理。 运行上面的代码可以在控制台看到如下结果: ~~~ ==============Java Bean >>> JSON Object================== {"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"haha"} ==============Java Bean >>> JSON Array================== [{"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"haha"}] ==============Java Bean >>> JSON Object ================== {"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"haha"} ========================JsonConfig======================== key:birthday {"address":"address","birthday":"2010-11-22##修改过的日期","email":"email","id":1,"name":"haha"} 2010-11-22##修改过的日期 haha#1#address#null#email #####################JsonPropertyFilter############################ haha#1#address#2010-11-22#email%%%address--address haha#1#address#2010-11-22#email%%%birthday--2010-11-22 haha#1#address#2010-11-22#email%%%email--email haha#1#address#2010-11-22#email%%%id--1 haha#1#address#2010-11-22#email%%%name--haha {"address":"address","email":"email","id":1,"name":"haha"} #################JavaPropertyFilter################## address@address#null#0#null#null#null birthday@2010-11-22##修改过的日期#null#0#address#null#null email@email#null#0#address#null#null id@1#null#0#address#null#null name@haha#null#0#address#null#null Student:haha#0#address#null#null ~~~ 2、 将JavaList集合转换吃JSON字符串 ~~~ /** * <b>function:</b>转换Java List集合到JSON * @author hoojo * @createDate Nov 28, 2010 2:36:15 PM */ @Test public void writeList2JSON() { fail("==============Java List >>> JSON Array=================="); List<Student> stu = new ArrayList<Student>(); stu.add(bean); bean.setName("jack"); stu.add(bean); fail(JSONArray.fromObject(stu).toString()); fail(JSONSerializer.toJSON(stu).toString()); } ~~~ 运行此方法后,可以看到控制台输出: ~~~ ==============Java List >>> JSON Array================== [{"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"jack"}, {"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"jack"}] [{"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"jack"}, {"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"jack"}] ~~~ 如果你是转换List集合,一定得用JSONArray或是JSONSrializer提供的序列化方法。如果你用JSONObject.fromObject方法转换List会出现异常,通常使用JSONSrializer这个JSON序列化的方法,它会自动识别你传递的对象的类型,然后转换成相应的JSON字符串。 3、 将Map集合转换成JSON对象 ~~~ /** * <b>function:</b>转Java Map对象到JSON * @author hoojo * @createDate Nov 28, 2010 2:37:35 PM */ @Test public void writeMap2JSON() { Map<String, Object> map = new HashMap<String, Object>(); map.put("A", bean); bean.setName("jack"); map.put("B", bean); map.put("name", "json"); map.put("bool", Boolean.TRUE); map.put("int", new Integer(1)); map.put("arr", new String[] { "a", "b" }); map.put("func", "function(i){ return this.arr[i]; }"); fail("==============Java Map >>> JSON Object=================="); fail(JSONObject.fromObject(map).toString()); fail("==============Java Map >>> JSON Array =================="); fail(JSONArray.fromObject(map).toString()); fail("==============Java Map >>> JSON Object=================="); fail(JSONSerializer.toJSON(map).toString()); } ~~~ 上面的Map集合有JavaBean、String、Boolean、Integer、以及Array和js的function函数的字符串。 运行上面的程序,结果如下: ~~~ ==============Java Map >>> JSON Object================== {"arr":["a","b"],"A":{"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"jack"},"int":1, "B":{"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"jack"},"name":"json", "func":function(i){ return this.arr[i]; },"bool":true} ==============Java Map >>> JSON Array ================== [{"arr":["a","b"],"A":{"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"jack"},"int":1, "B":{"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"jack"},"name":"json", "func":function(i){ return this.arr[i]; },"bool":true}] ==============Java Map >>> JSON Object================== {"arr":["a","b"],"A":{"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"jack"},"int":1, "B":{"address":"address","birthday":{"birthday":"2010-11-22"},"email":"email","id":1,"name":"jack"},"name":"json", "func":function(i){ return this.arr[i]; },"bool":true} ~~~ 4、 将更多类型转换成JSON ~~~ /** * <b>function:</b> 转换更多数组类型到JSON * @author hoojo * @createDate Nov 28, 2010 2:39:19 PM */ @Test public void writeObject2JSON() { String[] sa = {"a", "b", "c"}; fail("==============Java StringArray >>> JSON Array =================="); fail(JSONArray.fromObject(sa).toString()); fail(JSONSerializer.toJSON(sa).toString()); fail("==============Java boolean Array >>> JSON Array =================="); boolean[] bo = { true, false, true }; fail(JSONArray.fromObject(bo).toString()); fail(JSONSerializer.toJSON(bo).toString()); Object[] o = { 1, "a", true, 'A', sa, bo }; fail("==============Java Object Array >>> JSON Array =================="); fail(JSONArray.fromObject(o).toString()); fail(JSONSerializer.toJSON(o).toString()); fail("==============Java String >>> JSON =================="); fail(JSONArray.fromObject("['json','is','easy']").toString()); fail(JSONObject.fromObject("{'json':'is easy'}").toString()); fail(JSONSerializer.toJSON("['json','is','easy']").toString()); fail("==============Java JSONObject >>> JSON =================="); jsonObject = new JSONObject() .element("string", "JSON") .element("integer", "1") .element("double", "2.0") .element("boolean", "true"); fail(JSONSerializer.toJSON(jsonObject).toString()); fail("==============Java JSONArray >>> JSON =================="); jsonArray = new JSONArray() .element( "JSON" ) .element( "1" ) .element( "2.0" ) .element( "true" ); fail(JSONSerializer.toJSON(jsonArray).toString()); fail("==============Java JSONArray JsonConfig#setArrayMode >>> JSON =================="); List input = new ArrayList(); input.add("JSON"); input.add("1"); input.add("2.0"); input.add("true"); JSONArray jsonArray = (JSONArray) JSONSerializer.toJSON( input ); JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setArrayMode( JsonConfig.MODE_OBJECT_ARRAY ); Object[] output = (Object[]) JSONSerializer.toJava(jsonArray, jsonConfig); System.out.println(output[0]); fail("==============Java JSONFunction >>> JSON =================="); String str = "{'func': function( param ){ doSomethingWithParam(param); }}"; JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(str); JSONFunction func = (JSONFunction) jsonObject.get("func"); fail(func.getParams()[0]); fail(func.getText() ); } ~~~ 运行后结果如下: ~~~ ==============Java StringArray >>> JSON Array ================== ["a","b","c"] ["a","b","c"] ==============Java boolean Array >>> JSON Array ================== [true,false,true] [true,false,true] ==============Java Object Array >>> JSON Array ================== [1,"a",true,"A",["a","b","c"],[true,false,true]] [1,"a",true,"A",["a","b","c"],[true,false,true]] ==============Java String >>> JSON ================== ["json","is","easy"] {"json":"is easy"} ["json","is","easy"] ==============Java JSONObject >>> JSON ================== {"string":"JSON","integer":"1","double":"2.0","boolean":"true"} ==============Java JSONArray >>> JSON ================== ["JSON","1","2.0","true"] ==============Java JSONArray JsonConfig#setArrayMode >>> JSON ================== JSON ==============Java JSONFunction >>> JSON ================== param doSomethingWithParam(param); ~~~ 这里还有一个JSONFunction的对象,可以转换JavaScript的function。可以获取方法参数和方法体。同时,还可以用JSONObject、JSONArray构建Java对象,完成Java对象到JSON字符串的转换。 ### 三、JSON对象反序列化成Java对象 1、 将json字符串转成Java对象 ~~~ private String json = "{/"address/":/"chian/",/"birthday/":{/"birthday/":/"2010-11-22/"},"+ "/"email/":/"email@123.com/",/"id/":22,/"name/":/"tom/"}"; /** * <b>function:</b>将json字符串转化为java对象 * @author hoojo * @createDate Nov 28, 2010 3:01:16 PM */ @Test public void readJSON2Bean() { fail("==============JSON Object String >>> Java Bean =================="); jsonObject = JSONObject.fromObject(json); Student stu = (Student) JSONObject.toBean(jsonObject, Student.class); fail(stu.toString()); } ~~~ 运行后,结果如下: ~~~ ==============JSON Object String >>> Java Bean ================== tom#22#chian#2010-11-22#email@123.com ~~~ 2、 将json字符串转换成动态Java对象(MorphDynaBean) ~~~ private String json = "{/"address/":/"chian/",/"birthday/":{/"birthday/":/"2010-11-22/"},"+ "/"email/":/"email@123.com/",/"id/":22,/"name/":/"tom/"}"; @Test public void readJSON2DynaBean() { try { fail("==============JSON Object String >>> Java MorphDynaBean =================="); JSON jo = JSONSerializer.toJSON(json); Object o = JSONSerializer.toJava(jo);//MorphDynaBean fail(PropertyUtils.getProperty(o, "address").toString()); jsonObject = JSONObject.fromObject(json); fail(jsonObject.getString("email")); o = JSONSerializer.toJava(jsonObject);//MorphDynaBean fail(PropertyUtils.getProperty(o, "name").toString()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } ~~~ 转换后的对象Object是一个MorphDynaBean的动态JavaBean,通过PropertyUtils可以获得指定的属性的值。 运行后结果如下: ~~~ ==============JSON Object String >>> Java MorphDynaBean ============= chian email@123.com tom ~~~ 3、 将json字符串转成Java的Array数组 ~~~ private String json = "{/"address/":/"chian/",/"birthday/":{/"birthday/":/"2010-11-22/"},"+ "/"email/":/"email@123.com/",/"id/":22,/"name/":/"tom/"}"; @Test public void readJSON2Array() { try { fail("==============JSON Arry String >>> Java Array =================="); json = "[" + json + "]"; jsonArray = JSONArray.fromObject(json); fail("#%%%" + jsonArray.get(0).toString()); Object[] os = jsonArray.toArray(); System.out.println(os.length); fail(JSONArray.fromObject(json).join("")); fail(os[0].toString()); Student[] stus = (Student[]) JSONArray.toArray(jsonArray, Student.class); System.out.println(stus.length); System.out.println(stus[0]); } catch (Exception e) { e.printStackTrace(); } } ~~~ 运行的结果如下: ~~~ ==============JSON Arry String >>> Java Array ================== #%%%{"address":"chian","birthday":{"birthday":"2010-11-22"},"email":"email@123.com","id":22,"name":"tom"} 1 {"address":"chian","birthday":{"birthday":"2010-11-22"},"email":"email@123.com","id":22,"name":"tom"} {"address":"chian","birthday":{"birthday":"2010-11-22"},"email":"email@123.com","id":22,"name":"tom"} 1 tom#22#chian#2010-11-22#email@123.com ~~~ 4、 将JSON字符串转成Java的List集合 ~~~ private String json = "{/"address/":/"chian/",/"birthday/":{/"birthday/":/"2010-11-22/"},"+ "/"email/":/"email@123.com/",/"id/":22,/"name/":/"tom/"}"; @Test public void readJSON2List() { try { fail("==============JSON Arry String >>> Java List =================="); json = "[" + json + "]"; jsonArray = JSONArray.fromObject(json); List<Student> list = JSONArray.toList(jsonArray, Student.class); System.out.println(list.size()); System.out.println(list.get(0)); list = JSONArray.toList(jsonArray); System.out.println(list.size()); System.out.println(list.get(0));//MorphDynaBean } catch (Exception e) { e.printStackTrace(); } } ~~~ 运行后结果如下: ~~~ ==============JSON Arry String >>> Java List ================== 1 tom#22#chian#2010-11-22#email@123.com 1 net.sf.ezmorph.bean.MorphDynaBean@141b571[ {id=22, birthday=net.sf.ezmorph.bean.MorphDynaBean@b23210[ {birthday=2010-11-22} ], address=chian, email=email@123.com, name=tom} ] ~~~ 5、 将json字符串转换成Collection接口 ~~~ private String json = "{/"address/":/"chian/",/"birthday/":{/"birthday/":/"2010-11-22/"},"+ "/"email/":/"email@123.com/",/"id/":22,/"name/":/"tom/"}"; @Test public void readJSON2Collection() { try { fail("==============JSON Arry String >>> Java Collection =================="); json = "[" + json + "]"; jsonArray = JSONArray.fromObject(json); Collection<Student> con = JSONArray.toCollection(jsonArray, Student.class); System.out.println(con.size()); Object[] stt = con.toArray(); System.out.println(stt.length); fail(stt[0].toString()); } catch (Exception e) { e.printStackTrace(); } } ~~~ 刚才上面的将json转换成list提示该方法过时,这里有toCollection,可以用此方法代替toList方法;运行后结果如下: ~~~ ==============JSON Arry String >>> Java Collection ================== 1 1 tom#22#chian#2010-11-22#email@123.com ~~~ 6、 将json字符串转换成Map集合 ~~~ @Test public void readJSON2Map() { try { fail("==============JSON Arry String >>> Java Map =================="); json = "{/"arr/":[/"a/",/"b/"],/"A/":{/"address/":/"address/",/"birthday/":{/"birthday/":/"2010-11-22/"},"+ "/"email/":/"email/",/"id/":1,/"name/":/"jack/"},/"int/":1,/"B/":{/"address/":/"address/",/"birthday/":{/"birthday/":/"2010-11-22/"},"+ "/"email/":/"email/",/"id/":1,/"name/":/"jack/"},/"name/":/"json/",/"bool/":true}"; jsonObject = JSONObject.fromObject(json); Map<String, Class<?>> clazzMap = new HashMap<String, Class<?>>(); clazzMap.put("arr", String[].class); clazzMap.put("A", Student.class); clazzMap.put("B", Student.class); Map<String, ?> mapBean = (Map) JSONObject.toBean(jsonObject, Map.class, clazzMap); System.out.println(mapBean); Set<String> set = mapBean.keySet(); Iterator<String> iter = set.iterator(); while (iter.hasNext()) { String key = iter.next(); fail(key + ":" + mapBean.get(key).toString()); } } catch (Exception e) { e.printStackTrace(); } } ~~~ 运行后结果如下: ~~~ ==============JSON Arry String >>> Java Map ================== {A=jack#1#address#2010-11-22#email, arr=[a, b], B=jack#1#address#2010-11-22#email, int =1, name=json, bool=true} A:jack#1#address#2010-11-22#email arr:[a, b] B:jack#1#address#2010-11-22#email int :1 name:json bool:true ~~~ ### 四、JSON-lib对XML的支持 1、 将Java对象到XML ~~~ /*============================Java Object >>>>> XML ==========================*/ /** * <b>function:</b> 转换Java对象到XML * 需要额外的jar包:xom.jar * @author hoojo * @createDate Nov 28, 2010 2:39:55 PM */ @Test public void writeObject2XML() { XMLSerializer xmlSerializer = new XMLSerializer(); fail("==============Java String Array >>> XML =================="); //xmlSerializer.setElementName("bean"); fail(xmlSerializer.write(JSONArray.fromObject(bean))); String[] sa = {"a", "b", "c"}; fail("==============Java String Array >>> XML =================="); fail(xmlSerializer.write(JSONArray.fromObject(sa))); fail("==============Java boolean Array >>> XML =================="); boolean[] bo = { true, false, true }; fail(xmlSerializer.write(JSONArray.fromObject(bo))); fail(xmlSerializer.write(JSONSerializer.toJSON(bo))); Object[] o = { 1, "a", true, 'A', sa, bo }; fail("==============Java Object Array >>> JSON Array =================="); fail(xmlSerializer.write(JSONArray.fromObject(o))); fail(xmlSerializer.write(JSONSerializer.toJSON(o))); fail("==============Java String >>> JSON =================="); fail(xmlSerializer.write(JSONArray.fromObject("['json','is','easy']")).toString()); fail(xmlSerializer.write(JSONObject.fromObject("{'json':'is easy'}")).toString()); fail(xmlSerializer.write(JSONSerializer.toJSON("['json','is','easy']")).toString()); } ~~~ 主要运用的是XMLSerializer的write方法,这个方法可以完成java对象到xml的转换,不过你很容易就可以看到这个xml序列化对象,需要先将java对象转成json对象,然后再将json转换吃xml文档。 运行后结果如下: ~~~ ==============Java String Array >>> XML ================== <?xml version="1.0" encoding="UTF-8"?> <a><e class="object"><address type="string">address</address><birthday class="object"><birthday type="string">2010-11-22</birthday></birthday> <email type="string">email</email><id type="number">1</id><name type="string">haha</name></e></a> ==============Java String Array >>> XML ================== <?xml version="1.0" encoding="UTF-8"?> <a><e type="string">a</e><e type="string">b</e><e type="string">c</e></a> ==============Java boolean Array >>> XML ================== <?xml version="1.0" encoding="UTF-8"?> <a><e type="boolean">true</e><e type="boolean">false</e><e type="boolean">true</e></a> <?xml version="1.0" encoding="UTF-8"?> <a><e type="boolean">true</e><e type="boolean">false</e><e type="boolean">true</e></a> ==============Java Object Array >>> JSON Array ================== <?xml version="1.0" encoding="UTF-8"?> <a><e type="number">1</e><e type="string">a</e><e type="boolean">true</e><e type="string">A</e><e class="array"> <e type="string">a</e><e type="string">b</e><e type="string">c</e></e><e class="array"><e type="boolean">true</e> <e type="boolean">false</e><e type="boolean">true</e></e></a> <?xml version="1.0" encoding="UTF-8"?> <a><e type="number">1</e><e type="string">a</e><e type="boolean">true</e><e type="string">A</e><e class="array"> <e type="string">a</e><e type="string">b</e><e type="string">c</e></e><e class="array"><e type="boolean">true</e> <e type="boolean">false</e><e type="boolean">true</e></e></a> ==============Java String >>> JSON ================== <?xml version="1.0" encoding="UTF-8"?> <a><e type="string">json</e><e type="string">is</e><e type="string">easy</e></a> <?xml version="1.0" encoding="UTF-8"?> <o><json type="string">is easy</json></o> <?xml version="1.0" encoding="UTF-8"?> <a><e type="string">json</e><e type="string">is</e><e type="string">easy</e></a> ~~~ 上面的节点名称有点乱,你可以通过setElementName设置节点名称 2、 将XML转换成Java对象 ~~~ /*============================XML String >>>>> Java Object ==========================*/ /** * <b>function:</b>转换xml文档到java对象 * @author hoojo * @createDate Nov 28, 2010 3:00:27 PM */ @Test public void readXML2Object() { XMLSerializer xmlSerializer = new XMLSerializer(); fail("============== XML >>>> Java String Array =================="); String[] sa = {"a", "b", "c"}; jsonArray = (JSONArray) xmlSerializer.read(xmlSerializer.write(JSONArray.fromObject(sa))); fail(jsonArray.toString()); String[] s = (String[]) JSONArray.toArray(jsonArray, String.class); fail(s[0].toString()); fail("============== XML >>>> Java boolean Array =================="); boolean[] bo = { true, false, true }; jsonArray = (JSONArray) xmlSerializer.read(xmlSerializer.write(JSONArray.fromObject(bo))); bo = (boolean[]) JSONArray.toArray(jsonArray, boolean.class); fail(bo.toString()); System.out.println(bo[0]); jsonArray = (JSONArray) xmlSerializer.read(xmlSerializer.write(JSONSerializer.toJSON(bo))); bo = (boolean[]) JSONArray.toArray(jsonArray, boolean.class); fail(bo.toString()); System.out.println(bo[0]); fail("==============Java Object Array >>> JSON Array =================="); Object[] o = { 1, "a", true, 'A', sa, bo }; jsonArray = (JSONArray) xmlSerializer.read(xmlSerializer.write(JSONArray.fromObject(o))); System.out.println(jsonArray.getInt(0)); System.out.println(jsonArray.get(1)); System.out.println(jsonArray.getBoolean(2)); jsonArray = (JSONArray) xmlSerializer.read(xmlSerializer.write(JSONSerializer.toJSON(o))); System.out.println(jsonArray.get(4)); System.out.println(jsonArray.getJSONArray(5).get(0)); System.out.println(jsonArray.get(5)); fail("==============Java String >>> JSON =================="); jsonArray = (JSONArray) xmlSerializer.read(xmlSerializer.write(JSONArray.fromObject("['json','is','easy']")).toString()); s = (String[]) JSONArray.toArray(jsonArray, String.class); fail(s[0].toString()); jsonObject = (JSONObject) xmlSerializer.read(xmlSerializer.write(JSONObject.fromObject("{'json':'is easy'}")).toString()); Object obj = JSONObject.toBean(jsonObject); System.out.println(obj); jsonArray = (JSONArray) xmlSerializer.read(xmlSerializer.write(JSONSerializer.toJSON("['json','is','easy']")).toString()); s = (String[]) JSONArray.toArray(jsonArray, String.class); fail(s[1].toString()); } ~~~ 主要运用到XMLSerializer的read方法,将xml内容读取后,转换成Java对象。运行后结果如下: ~~~ ============== XML >>>> Java String Array ================== ["a","b","c"] a ============== XML >>>> Java boolean Array ================== [Z@15856a5 true [Z@79ed7f true ==============Java Object Array >>> JSON Array ================== 1 a true ["a","b","c"] true ["true","false","true"] ==============Java String >>> JSON ================== json net.sf.ezmorph.bean.MorphDynaBean@c09554[ {json=is easy} ] is ~~~ 3、 将xml的字符串内容,转换成Java的Array对象 ~~~ @Test public void testReadXml2Array() { String str = "<a class=/"array/">" + "<e type=/"function/" params=/"i,j/">" + "return matrix[i][j];" + "</e>" + "</a>"; JSONArray json = (JSONArray) new XMLSerializer().read(str); fail(json.toString()); } ~~~ 上面是一段xml字符串格式的文档,将其转换为JSONArray对象。转换后结果如下: ~~~ [function(i,j){ return matrix[i][j]; }] ~~~ 就是一个数组;
';

前言

最后更新于:2022-04-01 14:22:12

> 原文出处:[JSON/XML 专栏](http://blog.csdn.net/column/details/json-xml.html) 作者:[ibm_hoojo](http://blog.csdn.net/ibm_hoojo) **本系列文章经作者授权在看云整理发布,未经作者允许,请勿转载!** # JSON/XML 专栏 > 介绍JSON/XML在Java/JavaScript、jQuery 中常用的框架、技术文章;
';