JAXB XML和Bean互相轉換


JAXB(Java Architecture for XML Binding) 是一個業界的標准,是一項可以根據XML Schema產生Java類的技術。該過程中,JAXB也提供了將XML實例文檔反向生成Java對象樹的方法,並能將Java對象樹的內容重新寫到XML實例文檔。是JDK的組成部分

JDK中JAXB相關的重要Class和Interface:

JAXBContext類,是應用的入口,用於管理XML/Java綁定信息。
Marshaller接口,將Java對象序列化為XML數據。
Unmarshaller接口,將XML數據反序列化為Java對象。

 

當使用 @XmlRootElement 注釋對頂層類或枚舉類型進行注釋時,類型值被表示為 XML 文檔中的 XML 元素。

JAXB Annotation

  • @XmlRootElement   // xml 文件的根元素 將Java類或枚舉類型映射到XML元素(必須使用 指定xml跟元素)
  • @XmlElement    //將Java類的一個屬性映射到與屬性同名的一個XML元素
  • @XmlAccessorType  // 控制默認情況下是否對字段或 Javabean 屬性進行系列化(必須使用 指定如何轉化)。
  • @XmlTransient
  • @XmlJavaTypeAdaptor:參考Using JAXB 2.0's XmlJavaTypeAdapter



XmlAccessorType 
默認規則:
默認情況下,如果包中不存在 @XmlAccessorType,那么假定使用以下包級別注釋。
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
默認情況下,如果類中不存在 @XmlAccessorType,並且沒有任何超類是使用 @XmlAccessorType 注釋的,則假定在類中使用以下默認注釋:
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
可能值:
FIELD:    JAXB 綁定類中的每個非靜態、非瞬態字段將會自動綁定到 XML,除非由 XmlTransient 注釋。
NONE:     所有字段或屬性都不能綁定到 XML,除非使用一些 JAXB 注釋專門對它們進行注釋。
PROPERTY: JAXB 綁定類中的每個獲取方法/設置方法(get/set方法)對將會自動綁定到 XML,除非由 XmlTransient 注釋。
PUBLIC_MEMBER:每個公共獲取方法/設置方法對和每個公共字段將會自動綁定到 XML,除非由 XmlTransient 注釋。

Java Bean轉換成XML實例:

實體類:

@XmlRootElement(name = "person")
@XmlAccessorType(XmlAccessType.FIELD)
public class Person {

    private String name;
    private Integer age;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

 

轉換代碼:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class JAXBTest {
    public static void main(String[] args) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(Person.class);

        Marshaller marshaller = context.createMarshaller();
        Unmarshaller unmarshaller = context.createUnmarshaller();

        Person person = new Person();
        person.setAge(11);
        person.setName("測試");
        marshaller.marshal(person, System.out);
        System.out.println();
    }
}

輸出結果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><person><name>測試</name><age>11</age></person>

 

XML轉換成Bean實例:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;

public class JAXBTest {
    public static void main(String[] args) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(Person.class);

        Unmarshaller unmarshaller = context.createUnmarshaller();

        String xml = "<person><age>11</age><name>測試</name></person>";
        Person person = (Person) unmarshaller.unmarshal(new StringReader(xml));
        System.out.println(person.getAge());
    }
}

 

XML轉換成Bean是有命名空間的情況:

public class JAXBTest {
    public static void main(String[] args) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(Person.class);

        Unmarshaller unmarshaller = context.createUnmarshaller();

        String xml = "<person xmlns=\"http://test.org/\"><age>11</age><name>測試</name></person>";
        Person person = (Person) unmarshaller.unmarshal(new StringReader(xml));
        System.out.println(person.getAge());
    }
}

會報錯:

Exception in thread "main" javax.xml.bind.UnmarshalException: 意外的元素 (uri:"http://test.org/", local:"person")。所需元素為<{}person>
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:109)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1131)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:556)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:538)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:153)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:613)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3132)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:852)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:214)

 

一種處理方法就是XML轉換成Bean的時候忽略命名空間:

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;
import java.io.StringReader;

public class JAXBTest {
    public static void main(String[] args) throws JAXBException, ParserConfigurationException, SAXException {

        JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        String xml = "<person xmlns=\"http://test.org/\"><age>11</age><name>測試</name></person>";
        StringReader reader = new StringReader(xml);
        SAXParserFactory sax = SAXParserFactory.newInstance();
        sax.setNamespaceAware(false);//設置忽略明明空間
        XMLReader xmlReader = sax.newSAXParser().getXMLReader();
        Source source = new SAXSource(xmlReader, new InputSource(reader));

        Person person = (Person) unmarshaller.unmarshal(source);
        System.out.println(person.getAge());
    }
}

 

如果我們的根元素沒有子元素並且里面有值 而且我們需要解析XML獲取這個值的時候 一種解決辦法:修改我們的Bean注解 這樣就能正確轉化成Bean

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;

@XmlRootElement(name = "string")
public class XMLToBeanlVo {
    private String stringValue;

    @XmlValue
    public String getStringValue() {
        return stringValue;
    }

    public void setStringValue(String stringValue) {
        this.stringValue = stringValue;
    }
}

 

將xml中多個相同的元素解析成java中的list

<?xml version="1.0" encoding="GBK" ?>
<reports>
<report>
<name>test</name>
<mobile>13810000001</mobile>
</report>
<report>
<name>test</name>
<mobile>13810000002</mobile>
</report>
</reports>

java實體類:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "reports")
public class XmlVo {
    @XmlElement(name = "report")
    private List<DetailXmlVo> report;

    public List<DetailXmlVo> getReport() {
        return report;
    }

    public void setReport(List<DetailXmlVo> report) {
        this.report = report;
    }
}
public class DetailXmlVo {
    private String name;
    private String mobile;
}

 

參考:https://www.cnblogs.com/Nouno/p/5728112.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM