是一種java和xml轉換的工具
以下以一個一對多的方式為例
※Employee.java
public class Employee { private String name; private int id; // setter/getter... public Employee(String name, int id) { super(); this.name = name; this.id = id; } public Employee() {} }
※預設建構子在java轉xml時會用到
※Dept.java
@XmlRootElement public class Dept { private String name; private int did; private List<Employee> emps; // setter/getter... public Dept(String name, int did, List<Employee> emps) { super(); this.name = name; this.did = did; this.emps = emps; } public Dept() {} }
※預設建構子在xml轉java時會用到
※java轉xml
public void javaToXml() throws JAXBException { JAXBContext jaxb = JAXBContext.newInstance(Dept.class); Marshaller ms = jaxb.createMarshaller(); List<Employee> list = new ArrayList<>(); list.add(new Employee("Bruce", 123)); list.add(new Employee("Jacky", 456)); list.add(new Employee("Mary", 789)); ms.marshal(new Dept("information", 2, list), System.out); ms.marshal(new Dept("information", 2, list), new File("D:/jaxb.xml")); }
※JAXBContext.newInstance裡面的類別必須要有@XmlRootElement
※屬性名為xml的標籤名,一對多的Employee叫emps,所以<emps>下會有它裡面的屬性<id>和<name>
※如果屬性是Map,那會變成
<屬性名><entry><key /><value /></entry> <entry><key /><value /></entry></屬性名>
※xml轉java
public void xmlToJava() throws JAXBException { String line = System.getProperty("line.separator"); String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + line + "<dept><did>2</did><emps><id>123</id><name>Bruce</name></emps>" + line + "<emps><id>456</id><name>Jacky</name></emps>" + line + "<emps><id>789</id><name>Mary</name></emps>" + line + "<name>information</name></dept>"; JAXBContext jaxb = JAXBContext.newInstance(Dept.class); Unmarshaller um = jaxb.createUnmarshaller(); // 使用String Dept dept1 = (Dept) um.unmarshal(new StringReader(xml)); System.out.println(dept1.getName()); System.out.println(dept1.getEmps().get(0).getName()); System.out.println(dept1.getEmps().get(1).getName()); System.out.println("=========="); // 使用File Dept dept2 = (Dept) um.unmarshal(new File("D:/jaxb.xml")); System.out.println(dept2.getName()); System.out.println(dept2.getEmps().get(0).getName()); System.out.println(dept2.getEmps().get(1).getName()); }
※不管tag和tag之間有沒有空隔、tab、換行,我試的結果都是可以的
※@XmlRootElement、@XmlAccessorType、@XmlElement、@XmlTransient、@XmlType、@XmlAttribute、@XmlAccessorOrder
這幾個Annotation 都是在 javax.xml.bind.annotation套件裡,裡面有很多,但這幾個比較常用※Dept.java
@XmlType(propOrder={"did", "name"}) @XmlRootElement(name = "root") @XmlAccessorType(XmlAccessType.FIELD) public class Dept { @XmlElement(name = "first") private String name; @XmlElement private int did; @XmlTransient private List<Employee> emps; // ... }
※@XmlRootElement是一定要有的,預設name名稱就是class名稱,所以tag會變成Dept,如果想改可以自行定義,像我上面的例子改成root
※@XmlTransient:不產生xml
※@XmlAccessorType 有以下4種:
FIELD:產生的xml,以成員變數為名
PROPERTY:產生的xml,以setter/getter為名,setter/getter為一組,少一個叫不會產生xml
PUBLIC_MEMBER:此為預設值,以setter/getter為名,但還得是public
NONE:整個類別不產生xml
※@XmlElement是針對子元素的,如果想改名,不能為null…等,都可在這設定
要注意@XmlAccessorType的設定會影響非類別註解寫的位置
.如果@XmlAccessorType設為FIELD,那麼註解要設在field才有效
.如果@XmlAccessorType設為PROPERTY,那麼這個註解要設在getter才有效;設在setter會報錯
.如果@XmlAccessorType是預設的PUBLIC_MEMBER,不能設定@XmlElement,會報「類別有相同名稱~」的錯
.如果@XmlAccessorType設為NONE,設定@XmlElement還是有效
※@XmlType的propOrder裡面除了已經註解為@XmlTransient以外,通通都得把元素寫出來,否則會報錯,它的功能是將產生的xml,以這裡的設定為順序(不是@XmlElement裡的name)
.其他的屬性是針對Schema用的,在這裡看不出來有什麼不同
.@XmlAccessorOrder也是排序的,但只有兩個值
UNDEFINED:預設值,以java的順序為主(不是@XmlElement裡的name)
ALPHABETICAL:由a~z的順序為主(不是@XmlElement裡的name)
.兩個註解都下不會出錯,但為了必免混亂,最好只下一個
※@XmlAttribute為設定屬性的,如將did上面的註解改成這個,那did會變成Dept的屬性,當然也有name可以改變顯示的名字
.不能與@XmlElement同時使用,否則會產生「~含有互斥的註解~」的錯
※@XmlJavaTypeAdapter
為xml和java型態轉換用的,以下用一個日期轉換格式為例使用這個annotation要寫一個class繼承XmlAdapter
我試過在Dept.java裡寫一個類別,不管是private、protected、default,都會出錯
※Dept.java
@XmlRootElement public class Dept { @XmlJavaTypeAdapter(DateAdapter.class) private Date date; public Dept() {} public Dept(Date date) { this.date = date; } }
※DateAdapter.java
public class DateAdapter extends XmlAdapter<String, Date> { DateFormat fmt = new SimpleDateFormat("yyyyMMdd HHmmss"); @Override public Date unmarshal(String v) throws Exception { return fmt.parse(v); } @Override public String marshal(Date v) throws Exception { return fmt.format(v); } }
※測試類
JAXBContext jaxb = JAXBContext.newInstance(Dept.class); Marshaller ms = jaxb.createMarshaller(); jaxb.createMarshaller().marshal(new Dept(new Date()), System.out);
沒有留言:
張貼留言