Java中提供一套用于XML与Bean转换的工具javax.xml.bind.JAXBContext
先说结论,在定义Bean时,要保证其默认无参的构造函数不能被覆盖。(即如果定义了其它构造函数,则默认无参构造函数要显示定义)
JAXB实现对象与xml互转注解:
1.@XmlRootElement,用于类级别的注解,对应xml的跟元素。通过name属性定义这个根节点的名称。
2.@XmlAccessorType,定义映射这个类中的何种类型都需要映射到xml。(如果不存在@XmlAccessorType,默认使用XmlAccessType.PUBLIC_MEMBER注解)
参数:XmlAccessType.FIELD: java对象中的所有成员变量。
XmlAccessType.PROPERTY:java对象中所有通过getter/setter方式访问的成员变量。
XmlAccessType.PUBLIC_MEMBER:java对象中所有的public访问权限的成员变量和通过getter/setter方式访问的成员变量。
XmlAccessType.NONE: java对象的所有属性都不映射为xml的元素。
3.@XmlAttribute,用于把java对象的属性映射为xml的属性,并可通过name属性为生成的xml属性指定别名。
4.@XmlElement,指定一个字段或get/set方法映射到xml的节点。通过name属性定义这个根节点的名称。
5.@XmlElementWrapper,为数组或集合定义一个父节点。通过name属性定义这个父节点的名称
package com.zte.sunquan.jaxb; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import java.util.ArrayList; import java.util.List; /** * Created by xxx on 2017/10/20. */ @XmlRootElement(name = "person") public class Person { @XmlAttribute(name = "name") public String name; @XmlAttribute(name = "age") public int age; public Person() { } private List<String> hobby=new ArrayList<>(); public Person(String name) { this.name = name; } @XmlElementWrapper(name = "hobbys") @XmlElement(name = "hobby") public List<String> getHobby() { return hobby; } public void addHobby(String hobby) { this.hobby.add(hobby); } }
上面的Bean,对于无参构造函数显示增加了定义
在源码com.sun.xml.bind.v2.model.impl.ClassInfoImpl.java构造函数中,会对类是否有默认构造函数进行校验
// the class must have the default constructor if (!hasFactoryConstructor(t)){ if(!nav().hasDefaultConstructor(clazz)){ if(nav().isInnerClass(clazz)) { builder.reportError(new IllegalAnnotationException( Messages.CANT_HANDLE_INNER_CLASS.format(nav().getClassName(clazz)),this )); } else if (elementName != null) { builder.reportError(new IllegalAnnotationException( Messages.NO_DEFAULT_CONSTRUCTOR.format(nav().getClassName(clazz)),this )); } } }
测试脚本:
package com.zte.sunquan.jaxb; import org.junit.Before; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.transform.dom.DOMResult; import java.io.StringReader; import java.io.StringWriter; import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertEquals; /** * Created by xxx on 2017/10/20. */ public class PersonTest { private Person person; int age = 29; String name = "Foo"; String hobby = "singing"; @Before public void init() { person = new Person("xy"); person.name = name; person.age = age; person.addHobby(hobby); } @Test public void testMarshallerDocument() throws JAXBException { JAXBContext context = JAXBContext.newInstance(person.getClass()); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);//格式化xml输出 DOMResult res = new DOMResult(); marshaller.marshal(person,res); Element doc = ((Document) res.getNode()).getDocumentElement(); assertEquals(name,doc.getAttribute("name")); assertEquals(age,Integer.parseInt(doc.getAttribute("age"))); //((Document) res.getNode()).getDocumentElement() NodeList hobbys = doc.getChildNodes(); assertEquals(hobby,hobbys.item(0).getTextContent()); } @Test public void testMarshallerString() throws JAXBException { JAXBContext context = JAXBContext.newInstance(person.getClass()); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);//格式化xml输出 StringWriter writer = new StringWriter(); marshaller.marshal(person,writer); String outString = writer.toString(); System.out.println(outString); assertTrue(outString.contains("</person")); } @Test public void testUnMarshaller() throws JAXBException { String outString = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + "<person name=\"Foo\" age=\"29\">\n" + " <hobbys>\n" + " <hobby>singing</hobby>\n" + " </hobbys>\n" + "</person>"; JAXBContext context = JAXBContext.newInstance(Person.class,Person.class); Unmarshaller unmarshaller = context.createUnmarshaller(); StringReader reader = new StringReader(outString); Person reciever = (Person) unmarshaller.unmarshal(reader); assertEquals(name,reciever.name); assertEquals(age,reciever.age); assertEquals(hobby,reciever.getHobby().get(0)); } }