Java序列化(XML和JSON)及XStream与JAXB的比较

其实XStream和JAXB在一些观念上是很相似的,但是JAXB作为Java EE的一个规范,是非常正式的,且和其他很多规范有联系 是一种标准的实现。

区别:

jaxb2如果没有加@XmlElement等注释,是不会写入到xml中的,但是XStream不会

XStream没有加上注释,默认以属性名称写入子级的元素中

XStream还可以将bean转为json,功能比较强悍,个人建议使用XStream

 

一、JAXB

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

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

JAXBContext类,是应用的入口,用于管理XML/Java绑定信息。 
Marshaller接口,将Java对象序列化为XML数据。 
Unmarshaller接口,将XML数据反序列化为Java对象。 
JDK中JAXB相关的重要Annotation:(来源于百度百科JAXB)

@XmlType,将Java类或枚举类型映射到XML模式类型 
@XmlAccessorType(XmlAccessType.FIELD) ,控制字段或属性的序列化。FIELD表示JAXB将自动绑定Java类中的每个非静态的(static)、非瞬态的(由@XmlTransient标注)字段到XML。其他值还有XmlAccessType.PROPERTY和XmlAccessType.NONE。 
@XmlAccessorOrder,控制JAXB 绑定类中属性和字段的排序。 
@XmlJavaTypeAdapter,使用定制的适配器(即扩展抽象类XmlAdapter并覆盖marshal()和unmarshal()方法),以序列化Java类为XML。 
@XmlElementWrapper ,对于数组或集合(即包含多个元素的成员变量),生成一个包装该数组或集合的XML元素(称为包装器)。 
@XmlRootElement,将Java类或枚举类型映射到XML元素。 
@XmlElement,将Java类的一个属性映射到与属性同名的一个XML元素。 
@XmlAttribute,将Java类的一个属性映射到与属性同名的一个XML属性。

在以上的注解中,用的最多的是@XMLType,@XmlAccessorType,@XmlRootElement。

实现步骤:

1.一个实体类,使用@XmlRootElement表示一下类(最简单的)

2.建立一个ObjectFactory用来产生这个实体类

3.使用JAXBContext 然后产生Marshaller(对象-->xml)或者UnMarshaller(xml-->对象)

示例代码:

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Calendar;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

public class JAXB2Tester { 

    public static void main(String[] args) throws JAXBException,IOException { 
        JAXBContext context = JAXBContext.newInstance(Person.class); 
        //下面代码演示将对象转变为xml 
        Marshaller m = context.createMarshaller(); 
        Address address = new Address("China","Beijing","Beijing","ShangDi West","100080"); 
        Person p = new Person(Calendar.getInstance(),"JAXB2",address,Gender.MALE,"SW"); 
        FileWriter fw = new FileWriter("person.xml"); 
        m.marshal(p,fw); 

        //下面代码演示将上面生成的xml转换为对象 
        FileReader fr = new FileReader("person.xml"); 
        Unmarshaller um = context.createUnmarshaller(); 
        Person p2 = (Person)um.unmarshal(fr); 
        System.out.println("Country:"+p2.getAddress().getCountry());
    } 
}  

@XmlRootElement//表示person是一个根元素 
class Person {    
    @XmlElement 
    Calendar birthDay; //birthday将作为person的子元素 

    @XmlAttribute 
    String name; //name将作为person的的一个属性 

    public Address getAddress() { 
        return address; 
    } 

    @XmlElement 
    Address address; //address将作为person的子元素 

    @XmlElement 
    Gender gender; //gender将作为person的子元素 

    @XmlElement 
    String job; //job将作为person的子元素 

    public Person(){ 

    } 

 

    public Person(Calendar birthDay, String name, Address address, Gender gender, String job) { 
        this.birthDay = birthDay; 
        this.name = name; 
        this.address = address; 
        this.gender = gender; 
        this.job = job; 
    } 
} 

enum Gender{ 
    MALE(true), 
    FEMALE (false); 
    private boolean value; 
    Gender(boolean _value){ 
        value = _value; 
    } 
} 

class Address { 
    @XmlAttribute 
    String country; 

    @XmlElement 
    String state; 

    @XmlElement 
    String city; 

    @XmlElement 
    String street; 

    String zipcode; //由于没有添加@XmlElement,所以该元素不会出现在输出的xml中 
    public Address() { 

    } 

    public Address(String country, String state, String city, String street, String zipcode) { 

        this.country = country; 
        this.state = state; 
        this.city = city; 
        this.street = street; 
        this.zipcode = zipcode; 
    } 

 

    public String getCountry() { 
        return country; 
    } 
} 

运行该程序,我们会得到一个person.xml的文件,如下: 

 
 
      2006-12-28T08:49:27.203+00:00 
       
              Beijing              Beijing              ShangDi West    
         MALE         SW 
 

控制台会输出 

Country:China 

 

 

二、XStream

1.首先从XStream官网下载XStream

http://xstream.codehaus.org/download.html

2.下载后解压 将lib下的jar添加入项目就可以了

如下:
Java序列化(XML和JSON)及XStream与JAXB的比较_第1张图片
 

然后就可以编写代码了,为了方便直接使用XStream的annotation:

3.实体类 Person:

package org.cc.vo;  
  
import java.util.List;  
  
import com.thoughtworks.xstream.annotations.XStreamAlias;  
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;  
import com.thoughtworks.xstream.annotations.XStreamImplicit;  
import com.thoughtworks.xstream.annotations.XStreamOmitField;  
  
@XStreamAlias("Person")  
public class Person {  
  
    @XStreamAlias("name")  
    @XStreamAsAttribute  
    private String name;  
      
    @XStreamAlias("age")  
    private int age;  
      
    @XStreamAlias("sex")  
    private boolean sex;  
      
    @XStreamImplicit(itemFieldName="favor")  
    private List favor;  
  
    @XStreamOmitField  
    private int tempid;  
      
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public int getAge() {  
        return age;  
    }  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
  
    public boolean isSex() {  
        return sex;  
    }  
  
    public void setSex(boolean sex) {  
        this.sex = sex;  
    }  
  
    public List getFavor() {  
        return favor;  
    }  
  
    public void setFavor(List favor) {  
        this.favor = favor;  
    }  
  
    public int getTempid() {  
        return tempid;  
    }  
  
    public void setTempid(int tempid) {  
        this.tempid = tempid;  
    }  
  
    @Override  
    public String toString() {  
        return "Person [name=" + name + ", age=" + age + ", sex=" + sex  
                + ", favor=" + favor + ", tempid=" + tempid + "]";  
    }  
  
  
  
}  

 

 @XStreamAlias(value)是别名 可以用在类名和属性名上修改显示的xml中的标签

 @XStreamAsAttribute 把属性作为xml中的属性 而不是子元素

 @XStreamImplicit(itemFieldName="favor") 还有一个keyFieldName的属性 这个是用来改写List和Map的显示 的

 @XStreamOmitField 此标记的属性不会序列化

 

4.接下去只有一步,没有JAXB的建立ObjectFactory那一部,实现起来非常简洁直观:

package org.cc.vo;  
  
import java.util.ArrayList;  
import java.util.List;  
  
import com.thoughtworks.xstream.XStream;  
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;  
  
public class Main {  
  
    public static void main(String[] args) {  
         XStream x=new XStream();  
//       XStream x = new XStream(new JettisonMappedXmlDriver());  
         x.processAnnotations(Person.class);  
         Person p=new Person();  
         p.setAge(30);  
         List fa=new ArrayList();  
         fa.add("游戏");  
         fa.add("上网");  
         p.setFavor(fa);  
         p.setName("cc");  
         String info=x.toXML(p);  
         System.out.println(info);  
           
         Person p2=(Person)x.fromXML(info);  
         System.out.println(p2);  
    }  
  
}  

 输出:

Xml代码 

  
  30  
  false  
  游戏  
  上网  
  
Person [name=cc, age=30, sex=false, favor=[游戏, 上网], tempid=0]  

注意了以上代码注释掉的那块打开 并把没有参数的构造方法的XStream那一段注释掉产生的就是JSON(换了一个引擎)

产生内容如下:

{"Person":{"@name":"cc","age":30,"sex":false,"favor":["游戏","上网"]}}  
Person [name=cc, age=30, sex=false, favor=[游戏, 上网], tempid=0] 

 

你可能感兴趣的:(Java)