使用JAXB类库实现JAVA对象与XML互转

零、前言

XML是开发中常用的配置文件类型,在常用的组件包里也能时常看到它的踪影,如Spring中的applicationContext.xml、Hibernate中的hbm.xml,都是用的XML来配置相关的参数信息。可见其使用是十分广泛的。

但是在Java中,要解析一个XML,并封装为一个对象,可能大家首先会想到Dom4j、Jdom等第三方类库,使用其中的解析器对每一个节点解析,并生成自己想要的对象。这样写的话,代码显得是很混乱,不是很易读。如果在Webservice交互中,用到XML传递数据,那么工作量就会更大了。

今天就要用一个非常好用的工具来解决这个问题。它就是JAXB类库。

一、介绍

JAXB允许JAVA开发人员将JAVA类映射为XML,也可以逆向的将XML转换为JAVA。可以不用手动的去写解析XML的方法,只需要书写对应的JAVA Bean,并配置好相应的注解,就可以完成转换,大大简化了程序员的工作量。

二、集成

讲了这么多,大家可能在想,如何集成呢,其实咱们不用集成就可以使用,这个功能是直接集成在JDK中的。完全不用集成,是不更简单呢,不用集成任何类库。

三、前置学习

JAXB实现转换是依赖于Annotation的,那么咱们应该如何使用呢,可以看下面各个Annotation的作用:

a)、@XmlRootElement

用来定义一个XML的根节点信息,其参数有name和namespace。

其中name用来定义根节点的名称,非必填。

namespace用来定义XML的命名空间,非必填。

例如下定义:

如果咱们定义了一个JAVA Bean,名叫Property:

public class Property {}

1.咱们给他加上@XmlRootElement信息:

@XmlRootElement
public class Property {}

那么用表明生成的XML的根节点就是类名的小写,如下:

2.如果定义了name信息,则根节点名称就会是你定义的名称:

@XmlRootElement(name="Test")
public class Property {
}

生成的XML如下:

3.如果定义了namespace,根节点就会显示出你定义的namespace,如下代码

@XmlRootElement(name = "Test", namespace = "com.jialeens")
public class Property {}

生成的XML如下

b)、@XmlAccessorType

控制字段或属性的序列化。常用的有XmlAccessType.FIELD、XmlAccessType.PROPERTY和XmlAccessType.NONE。

如果定义的是FIELD(全自动),则表明JAXB 绑定类中的每个非静态(static)、非瞬态(transient)字段将会自动绑定到 XML,除非由 XmlTransient 注释。

如果定义的是PROPERTY(半自动),则表明JAXB 绑定类中的每个获取方法(get)/设置方法(set)对将会自动绑定到 XML,除非由 XmlTransient 注释。需要注意的是要实现get/set方法。

如果定义的是NONE(手动),则表所有字段或属性都不能绑定到 XML,除非使用一些 JAXB 注释专门对它们进行注释。如果使用了这个属性,咱们就需要对每个要映射的成员变量做设置才可以。

1.XmlAccessType.FIELD

@XmlRootElement(name = "Test")
@XmlAccessorType(XmlAccessType.FIELD)
public class Property {
    public String name;
}

生成的xml如下


    a

2.XmlAccessType.PROPERTY

如果咱们定义的时候不生成get/set方法,看看效果。

@XmlRootElement(name = "Test")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Property {
    public String name;
}

输出结果

可以看到没有生成name的内容。

咱们现在生成get/set方法,再看看效果。

@XmlRootElement(name = "Test")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Property {
    public String name;

    public String getName() {
        return name;
    }

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

生成XML的结果如下


    a

可以看到,这个类型是和get/set方法是否存在相关,如果写get/set方法,就生成xml。

c)、@XmlElement

将Java类的一个属性映射到与属性同名的一个XML元素。例如上面的例子,生成的是一个子标签。


    a

d)、@XmlAttribute

将Java类的一个属性映射到与属性同名的一个XML属性。

    

如上,name是在Test标签内部,当作Test标签的一个属性。

e)、@XmlElementWrapper

对于数组或集合(即包含多个元素的成员变量),生成一个包装该数组或集合的XML元素(称为包装器)。

f)、@XmlTransient

阻止将 JavaBean 属性映射到 XML 表示形式。主要用来解决映射冲突的情况。

四、简单使用

上面说了这么多,大家可能还不是很理解到底应该怎么用,下面咱们来讲一个简单的例子。

XML–>JAVA

现在咱们有一段XML。如下结构。


    testKey
    testValue

咱们先分析一下这个XML,可以看到这个XML的根节点是property。其中有个属性是type。其下面有两个标签,分别是key和value。那么咱们可以先定义一个bean。

public class Property {
    /**
     * 键
     */
    private String key;
    /**
     * 值
     */
    private String value;
    /**
     * 类型
     */
    private String type;
    /**
     * @return the key
     */
    public String getKey() {
        return key;
    }
    /**
     * @param key
     *            the key to set
     */
    public void setKey(String key) {
        this.key = key;
    }
    /**
     * @return the value
     */
    public String getValue() {
        return value;
    }
    /**
     * @param value
     *            the value to set
     */
    public void setValue(String value) {
        this.value = value;
    }
    /**
     * @return the type
     */
    public String getType() {
        return type;
    }
    /**
     * @param type
     *            the type to set
     */
    public void setType(String type) {
        this.type = type;
    }
}

现在咱们先定义一下根节点,根节点咱们使用@XmlRootElement注解。这样配置@XmlRootElement(name=”property”)。

上面的XML里有一个属性type,咱们可以使用@XmlAttribute(name = “type”)来标注type的成员变量

对于name和value这两个成员变量,可以使用@XmlElement来标注。那么咱们的JAVA Bean可以改成这样。

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Property {
    /**
     * 键
     */
    @XmlElement(name = "key")
    private String key;
    /**
     * 值
     */
    @XmlElement(name = "value")
    private String value;
    /**
     * 类型
     */
    @XmlAttribute(name = "type")
    private String type;
    /**
     * @return the key
     */
    public String getKey() {
        return key;
    }
    /**
     * @param key
     *            the key to set
     */
    public void setKey(String key) {
        this.key = key;
    }
    /**
     * @return the value
     */
    public String getValue() {
        return value;
    }
    /**
     * @param value
     *            the value to set
     */
    public void setValue(String value) {
        this.value = value;
    }
    /**
     * @return the type
     */
    public String getType() {
        return type;
    }
    /**
     * @param type
     *            the type to set
     */
    public void setType(String type) {
        this.type = type;
    }
}

咱们现在写一个调用的测试类。如:

public class JaxbTest {
    @Test
    public void test() throws JAXBException, IOException {
        String xml = ""
                + ""
                + "testKey"
                + "testValue" + "";
        JAXBContext context;
        context = JAXBContext.newInstance(Property.class);
        Unmarshaller unmarshal = context.createUnmarshaller();
        Property obj = (Property) unmarshal.unmarshal(new StringReader(xml));
        System.out.println(obj.getKey());
        System.out.println(obj.getValue());
        System.out.println(obj.getType());
    }
}

是不是很简单,完全没有解析XML的代码。

testKey

testValue

string

JAVA–>XML

咱们还是用上面的例子来将一个JAVA Bean转换成一个XML,咱们只需要修改调用方法即可,如下。

public class JaxbTest {
    @Test
    public void test() throws JAXBException, IOException {
        Property a = new Property();
        a.setKey("testKey");
        a.setValue("testValue");
        a.setType("string");
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            JAXBContext jc = JAXBContext.newInstance(a.getClass());
            Marshaller m = jc.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            m.marshal(a, os);
            String xml = new String(os.toByteArray(), "UTF-8");
            System.out.println(xml);
        } finally {
            os.close();
        }
    }
}

结果如下:


    testKey
    testValue

五、实现一个通用的工具类

咱们可以针对上面两种转换的方式写一个工具类,如下:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;

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

/**
 * ObjectXML转换类
 * 
 * @param  对应的类
 */
public class JAXBUtil {

    /**
     * 对象转换为xml
     * 
     * @param element
     * @return
     * @throws JAXBException
     * @throws IOException
     */
    public String marshal(T element) throws JAXBException, IOException {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            JAXBContext jc = JAXBContext.newInstance(element.getClass());
            Marshaller m = jc.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            m.marshal(element, os);
            String xml = new String(os.toByteArray(), "UTF-8");
            return xml;
        } finally {
            os.close();
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public T unmarshal(Class c, String xml) throws JAXBException {
        JAXBContext context;
        context = JAXBContext.newInstance(c);
        Unmarshaller unmarshal = context.createUnmarshaller();
        T obj = (T) unmarshal.unmarshal(new StringReader(xml));
        return obj;

    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public T unmarshal(Class c, InputStream is) throws JAXBException {
        JAXBContext context;
        context = JAXBContext.newInstance(c);
        Unmarshaller unmarshal = context.createUnmarshaller();
        T obj = (T) unmarshal.unmarshal(is);
        return obj;
    }
}

上面的这个工具类就可以方便的把一个JAVA转换为一个MXL字符串,也可以把一个XML字符串或者一个XML输入流转换成一个JAVA对象了。

调用的时候也很简单。

public class JaxbTest {
    @Test
    public void test() throws JAXBException, IOException {
        Property a = new Property();
        a.setKey("testKey");
        a.setValue("testValue");
        a.setKey("testKey");
        JAXBUtil util = new JAXBUtil();
        System.out.println(util.marshal(a));
    }
}

讲了这么多,大家应该对JAVA和XML之间转换有了一定了解,下一次将会讲解复杂对象应该如何转换。

责编内容来自:冷乐的Blog (源链) | 更多关于

阅读提示:酷辣虫无法对本内容的真实性提供任何保证,请自行验证并承担相关的风险与后果!
本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 后端存储 » 使用JAXB类库实现JAVA对象与XML互转

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录