JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。

一、先看个简单的例子

实体类:UserInfo.java 

package com.demo.bean;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.Arrays;

@XmlRootElement
public class UserInfo {
    private int id;
    private String name;
    private String gender;
    private String addr;
    private String[] hobbys;

    public UserInfo() {
    }

    public UserInfo(int id, String name, String gender, String addr, String[] hobbys) {
        this.id = id;
        this.name = name;
        this.gender = gender;
        this.addr = addr;
        this.hobbys = hobbys;
    }
    @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 getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
    @XmlElement
    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }
    //使用@XmlElementWrapper注解后,将会在原xml结点上再包装一层xml
    //@XmlElementWrapper仅允许出现在集合属性上
    @XmlElementWrapper(name="allhobbys")
    @XmlElement(name="hobby")
    public String[] getHobbys() {
        return hobbys;
    }

    public void setHobbys(String[] hobbys) {
        this.hobbys = hobbys;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", addr='" + addr + '\'' +
                ", hobbys=" + Arrays.toString(hobbys) +
                '}';
    }
}

实战互转方法

import com.demo.bean.UserInfo;
import org.junit.Test;

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

public class Test01 {
    @Test
    public void test(){
        UserInfo user = new UserInfo(1,"张三","男","杭州",new String[]{"篮球","音乐"});
        String xmlStr = objToXML(user);
        System.out.println(xmlStr);
        System.out.println("---------------------------------------------------------------");
        UserInfo getUser = (UserInfo)xmlStrToObj(xmlStr,UserInfo.class);
        System.out.println(getUser);
        System.out.println("---------------------------------------------------------------");
        //编组输出到文件中
        objToXmlFile(user,"E:\\user.xml");
        UserInfo getUser1 = (UserInfo)xmlFileToObj("E:\\user.xml",UserInfo.class);
        System.out.println(getUser1);
    }

    public String objToXML(Object obj){
        try {
            //根据obj类生成上下文对象
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            //从上下文中获取Marshaller对象,用作将bean编组(转换)为xml
            Marshaller marshaller = context.createMarshaller();
            //设置编码格式(默认编码就是utf-8)
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");//GB2312
            //以下是为生成xml做的一些配置
            //是否格式化生成的xml,即按标签自动换行,否则就是一行输出
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE);
            // 是否省略xml头部信息,默认不省略(false)
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
            StringWriter stringWriter = new StringWriter();
            marshaller.marshal(obj, stringWriter);
            StringBuilder stringBuilders = new StringBuilder();
            return stringBuilders.append(stringWriter).toString();
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void objToXmlFile(Object obj,String fileUrl){
        try {
            File file = new File(fileUrl);
            //根据obj类生成上下文对象
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            //从上下文中获取Marshaller对象,用作将bean编组(转换)为xml
            Marshaller marshaller = context.createMarshaller();
            //设置编码格式(默认编码就是utf-8)
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");//GB2312
            //以下是为生成xml做的一些配置
            //是否格式化生成的xml,即按标签自动换行,否则就是一行输出
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            // 是否省略xml头部信息,默认不省略(false)
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
            marshaller.marshal(obj,file);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    public Object xmlStrToObj(String xmlStr,Class objClass){
        try {
            JAXBContext jc = JAXBContext.newInstance(objClass);
            Unmarshaller unmar = jc.createUnmarshaller();
            Object obj = unmar.unmarshal(new StringReader(xmlStr));
            return obj;
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return null;
    }

    public Object xmlFileToObj(String xmlFileUrl,Class objClass){
        try {
            File file = new File(xmlFileUrl);
            JAXBContext jc = JAXBContext.newInstance(objClass);
            Unmarshaller unmar = jc.createUnmarshaller();
            Object obj = unmar.unmarshal(file);
            return obj;
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return null;
    }
}

输出结果:

生成的user.xml文件

二、常用注解解析

1、@XmlRootElement

作用和用法:

  类级别的注解,将类映射为xml全局元素,也就是根元素。就像spring配置文件中的beans。上面的例子中我将该注解用在了UserInfo类上,生成了<userInfo>根元素。常与@XmlType,@XmlAccessorType,@XmlAccessorOrder连用。

属性:

  该注解含有name和namespace两个属性。namespace属性用于指定生成的元素所属的命名空间。name属性用于指定生成元素的名字,若不指定则默认使用类名小写作为元素名。修改上面的例子,在该注解上使用name属性:

2、@XmlElement

作用和用法:

  字段,方法,参数级别的注解。该注解可以将被注解的字段(非静态),或者被注解的get/set方法对应的字段映射为本地元素,也就是子元素。默认使用字段名或get/set方法去掉前缀剩下部分小写作为元素名(在字段名和get/set方法符合命名规范的情况下)。上面例子中,id、addr、name、gender、hobby 都被映射成了<person>元素的子元素。下文会配合@XmlAccessorType注解详细讲解该注解的用法。常与@XmlValue,@XmlJavaTypeAdapter,@XmlElementWrapper连用。

属性:

  该注解的属性常用的属性有有:name、nillable、required、namespace、defaultValue

  • name属性可以指定生成元素的名字,同@XmlRootElement注解的name属性一样,不再举例。
  • nillable属性可以指定元素的文本值是否可以为空,默认为false。
  • required属性可以指定该元素是否必须出现,默认为false。
  • namespace属性可以指定该元素所属的命名空间。
  • defaultValue属性可以指定该元素默认的文本值。

3、@XmlAttribute

作用和用法:

字段和方法级别的注解。该注解会将字段或get/set方法对应的字段映射成本类对应元素的属性,属性名默认使用字段名或get/set方法去掉前缀剩下部分首字母小写(在字段名和get/set方法符合命名规范的情况下)。修改上面例子:

属性:

  该注解有name,required,namespace三个属性。用法和@XmlElement注解相同。

4、@XmlTransient

作用和用法:

  类,字段,方法级别的注解。可使JAXB在映射xml元素时忽略被注解的类,字段,get/set对应字段。需要注意的是该注解与所有其他JAXB注释相互排斥,也就是说与其他注释连用就会报错。修改上面例子:

属性:

  该注解没有属性。

5、@XmlJavaTypeAdapter

作用和用法:

  包、类、字段,方法、参数级别的注解。解决java日期(Date),数字(Number)格式化问题。直接看例子,修改UserInfo类,添加一个Date类型字段:

自定义一个适配器来解决这个问题。该注解的用法就是自定义适配器并继承XmlAdapter类,实现里面的marshal和unmarshal方法,并在该注解上引用。修改例子:

自定义的DateAdapter:

public class DateAdapter extends XmlAdapter<String, Date> {
    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public Date unmarshal(String date) throws Exception {
        return SDF.parse(date);
    }

    @Override
    public String marshal(Date date) throws Exception {
        return SDF.format(date);
    }
}

6、@XmlAccessorOrder

作用和用法:

  包和类级别的注解。控制生成元素的顺序。

属性:

  只有一个value属性,可取的值是一个名为XmlAccessOrder的枚举类型的两个值,XmlAccessOrder.ALPHABETICAL 和 XmlAccessOrder.UNDEFINED。默认为XmlAccessOrder.UNDEFINED,代表按照类中字段的顺序生成元素的顺序。

另一个值则代表按照字母表的顺序对生成的元素排序。但奇怪的是,只有jaxb按照field生成元素时,默认值才会生效,否则总是按照字母表的顺序排序。

7、@XmlAccessorType

作用和用法:

  包和类级别的注解。javaEE的API对该注解的解释是:控制字段是否被默认序列化。通俗来讲,就是决定哪些字段或哪些get/set方法对应的字段会被映射为xml元素,需要注意的是字段或get/set方法的访问权限(public/private)会影响字段是否被映射为xml元素,下面会详细讲解。

属性:

  该注解只有一个value属性,可取的值是一个名为XmlAccessType的枚举类型里的值,下面详细看一下这几个值分别有什么用:

XmlAccessType.PROPERTY:

1.当使用了该值,只要字段有对应的get/set方法对(注意是成对出现,只有其中一个不会发生映射),不需要使用@XmlElement注解,不论该方法的访问权限是什么(即使是private),jaxb就会将该字段映射成xml元素。不过最好加上@XmlElement注解,get/set方法任选一个即可,都加上会报错。

2.若在一个字段有set/get方法对但又在字段上添加@XmlElement注解会报属性重复的错误。

3.若没有set/get方法对,则需要在字段上使用@XmlElement注解才可以映射为xml元素,否则不会发生映射。

4.若get/set方法上使用了@XmlTransient注解,但想要对应字段发生映射,需要在对应字段上添加@XmlElement注解,此时不会报错,并将该字段映射为xml元素。

XmlAccessType.FIELD:

1.每个非静态的字段(无论访问权限如何)都会被jaxb映射为xml元素,即使没有get/set方法对,即使没有使用@XmlElement元素,但最好加上该注解以表明该字段要被映射为xml元素。

2.虽然没有get/set方法对,也会发生映射,但加上get/set方法对也不会报错,因为我们经常会使用这两个方法。但注意,不能再在这两个方法上使用@XmlElement方法,否则会报属性重复的错误。

3.若在字段上使用了@XmlTransient注解,但还想让该字段发生映射,需要在该字段对应的get/set方法上添加@XmlElement

XmlAccessType.PUBLIC_MEMBER: (该值为默认值):

1.每个访问权限为public的字段,或者每个访问权限为public的get/set方法对,都会将字段映射为xml元素,即使不使用@XmlElement,但最好加上。不可同时存在public字段和对应的get/set方法对,不然会报属性重复的错误。

2.若使用@XmlElement注解,需要注意只能在字段或get/set方法添加,两者任选其一,否则会报属性重复的错误。

3.若字段不为public,get/set方法为public并使用了@XmlTransient,需要在字段上添加@XmlElement才会发生映射。

若字段为public并使用了@XmlTransient,get/set方法对不为public,需要在get/set方法上使用@XmlElement才会映射。

XmlAccessType.NONE:

任何字段,get/set方法对都不会发生映射,除非使用某些注解,如@XmlElement,@XmlElementWrapper等。

JAXB java类与xml互转的更多相关文章

  1. JAXB—Java类与XML文件之间转换

    JAXB-Java类与XML文件之间转换 简介         JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生 ...

  2. JAVA bean与XML互转的利器---XStream

    最近在项目中遇到了JAVA bean 和XML互转的需求, 本来准备循规蹈矩使用dom4j忽然想起来之前曾接触过的XStream, 一番研究豁然开朗,利器啊利器, 下来就XStream的一些用法与大家 ...

  3. 使用JDK自带的JAXB进行类和xml的互转

    Classroom.java public class Classroom { private int id; private String name; private int grade; publ ...

  4. 简单Java类与XML之间的转换

    需要的jar包:xmlpull_1_0_5.jar,xstream-1.4.1.jar) 1.工具类XstreamUtil package com.learn.util; import com.tho ...

  5. JAXB(Java Architecture for XML Binding)

    marshal(Java对象转化成XML) import javax.xml.bind.annotation.XmlRootElement; //指定根元素,其他属性默认为根元素的子元素 @XmlRo ...

  6. Java Jaxb JavaBean与XML互转

    1.Jaxb - Java Arcitecture for XML Binding 是业界的一个标准,是一项能够依据XML Schema产生Java类的技术. Jaxb2.0是Jdk1.6的组成部分. ...

  7. JAXB 实现java对象与xml之间互相转换

    首先熟悉一下JAXB实现对象与xml互转时常用的一些注解使用: 1.@XmlRootElement,用于类级别的注解,对应xml的跟元素.通过name属性定义这个根节点的名称. 2.@XmlAcces ...

  8. jaxb 专题一(JAXB 实现java对象与xml之间互相转换)

    首先熟悉一下JAXB实现对象与xml互转时常用的一些注解使用: 1.@XmlRootElement,用于类级别的注解,对应xml的跟元素.通过name属性定义这个根节点的名称. 2.@XmlAcces ...

  9. java生成解析xml的另外两种方法JAXB

     JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术.该过程中,JAXB也提供了将XML实例文档反 ...

随机推荐

  1. python-我的第一门编程语言

    一.认识python是一个偶然,由于大学不务正业,混迹于各种电脑维修群(本人专业商务经济专业),了解过C.JAVA.HTML5以及世界上最好的编程语言PHP and so on!了解也仅仅是了解. 二 ...

  2. 微信小程序云开发

    什么是云开发? 云开发是由腾讯云联合微信团队为开发者提供的 包含 云函数.云数据库和云文件存储能力的后端云服务 云开发为开发者提供完整的云端支持,弱化后端和运维概念,无需搭建服务器,使用平台提供的 A ...

  3. pytest使用笔记(二)——pytest+allure配置使用

    使用环境及预置条件 开发工具:pycharm 操作系统:win10 开发语言:python3.6 使用库:pytest4.0,pytest-allure-adaptor 注意不要安装allure-py ...

  4. TPO-22 C1 Complain about a biased article

    /* 加粗:语音部分 * 红色:单词部分 * 斜体:语法部分 * 下划线:信号词/句 */ 第 1 段 1.Listen to a conversation between a student and ...

  5. GNU Radio GRC HackRF实现FM接收

    本文内容.开发板及配件仅限用于学校或科研院所开展科研实验! 淘宝店铺名称:开源SDR实验室 HackRF链接:https://item.taobao.com/item.htm?spm=a1z10.1- ...

  6. Google hack语法

    基础语法: 1.语法说明: inurl: 在url地址栏中显示的信息页面 intext: 显示在正文信息中的内容页面 site: 限制显示你某个域名的所有页面 filetype: 搜索文件的后缀或者扩 ...

  7. java并发编程原理

    一.java内存模型 Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样底层细节.此处的变量与Java编程时所说的变量不一样,指包括了实例字段 ...

  8. Java里字符串split方法

    Java中的split方法以"."切割字符串时,需要转义 String str[] = s.split("\\.");

  9. 在写ssh项目时浏览器页面出现http status 404 – not found

    HTTP Status 404 - /streetManager/index.jsp type Status report message /streetManager/index.jsp descr ...

  10. My Sql数据库设置环境变量和字符集

    一.踩坑背景 之前开发中一直用的是sql  server 数据库,最近接到公司一个老的项目,用的my sql数据库做的,功能做了一大部分,现在客户要求对原程序和数据库进行服务器的迁移工作.产品经理给出 ...