首页 > 技术文章 > XStream简单入门

ut2016-progam 2016-11-15 18:37 原文

简单的讲,XStream 涉及的就五个知识点:详情参考 官网

混叠,注解,转换器,对象流和操作json!

 

下面就用几个简单的例子来实现上述五个知识点!

基本步骤:

第1步:创建XStream对象。

通过它传递一个StaxDriver创建XStream对象。StaxDriver使用SAX解析器(可从Java6),一个快速的XML解析器。

XStream xstream = new XStream(new StaxDriver());

第2步:序列化对象到XML。

使用toXML() 方法来获取对象的XML字符串表示。

//Object to XML ConversionString xml = xstream.toXML(student);

第3步:反序列化XML获得对象。

使用 fromXML()方法来从XML对象。

//XML to Object Conversion Student student1 = (Student)xstream.fromXML(xml);

 

例一:

通过实体生成xml

public class Student {
    private String firstName;
    private String lastName;
    private int className;
    private int rollNo;
    private Address address;

    public void setAddress(Address address) {
        this.address = address;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public void setRollNo(int rollNo) {
        this.rollNo = rollNo;
    }

    @Override
    public String toString() {
        return "Student{" +
                "address=" address +
                ", firstName='" firstName '\'+
                ", lastName='" lastName '\'+
                ", className=" className +
                ", rollNo=" rollNo +
                '}';
    }
}


public class Address
{
    private String area;
    private String city;
    private String state;
    private String country;
    private int pincode;

    public void setArea(String area) {
        this.area = area;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public void setPincode(int pincode) {
        this.pincode = pincode;
    }
    public void setState(String state) {
        this.state = state;
    }
    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("\nAddress [ ");
        stringBuilder.append("\narea: ");
        stringBuilder.append(area);
        stringBuilder.append("\ncity: ");
        stringBuilder.append(city);
        stringBuilder.append("\nstate: ");
        stringBuilder.append(state);
        stringBuilder.append("\ncountry: ");
        stringBuilder.append(country);
        stringBuilder.append("\npincode: ");
        stringBuilder.append(pincode);
        stringBuilder.append(" ]");
        return stringBuilder.toString();
    }
}

public class Xstream_Test {
    public static void main(String... args){
        XStream xstream=new XStream(new DomDriver());
        Student student=getStudentDetail();
//        xstream.alias("student", Student.class);//生成开头的别名!!去掉全包名
        String xml=xstream.toXML(student);
        System.out.println(formatXml(xml));
    }

    private static Student getStudentDetail(){
        Student student=new Student();
        student.setFirstName("Mahesh");
        student.setLastName("Parashar");
        student.setRollNo(1);

        Address address=new Address();
        address.setArea("h.no. preet vihar.");
        address.setCity("delhi");
        address.setState("india");
        address.setPincode(12211);
        student.setAddress(address);
        return student;
    }
}

 

输出结果

 

发现输出,有类的包名

//类混叠是用来创建一个类的XML完全限定名称的别名。添加代码去掉全包名
xstream.alias("student", Student.class);

再输出结果,com.it5.xstream_demo.xml_2.Student 就会被 student别名取代!!

 

如果要给student加属性那要咋办??看例二

例二

通过类混叠,字段混叠为类与字段创建别名及属性!

public class Student {
    public String studentName;
    public String age;
    public List<Note> notes=new ArrayList<>();

    public Student(String name,String age) {
        this.studentName = name;this.age=age;
    }

    public void addNote(Note note) {
        notes.add(note);
    }
}

 

public class Note {
    public String title;
    public String description;

    public Note(String title,String description) {
        this.description = description;
        this.title = title;
    }
}

 

测试

public class Xstream_test_3 {
    private static Student getStudentDetails() {
        Student student=new Student("Mahesh","21");
        student.addNote(new Note("first","my first name!"));
        student.addNote(new Note("second","my second name!"));
        return student;
    }

    public static void main(String... args) {
        XStream xstream=new XStream(new DomDriver());
        Student student=getStudentDetails();
       

//类混叠使用
xstream.alias("student", Student.class);
xstream.alias("note",Note.class);
//字段混叠使用
xstream.aliasField("name",Student.class,"studentName");
//属性混叠使用
xstream.aliasAttribute(Student.class,"studentName","name");
xstream.aliasAttribute(Student.class,"age","age");
//隐式集合混叠
xstream.addImplicitCollection(Student.class"notes");

 

        String xml=xstream.toXML(student);
        System.out.println(XmlUtil.formatXml(xml));
    }
}

 

输出结果如下:

 

我们发现三处好像与平时见过的xml不一样的地方!!红线标注了!

1,studentName 与 age 应作为student的属性

2.集合的名字不应出现

要想达到想要的效果,这里就出现三个概念

类混叠:表示在XML无需显示类的全包名。

属性混叠:表示在XML显示属性名。

隐式集合混叠:表示在XML无需显示集合根名。

添加如下代码如下;

//类混叠使用
xstream.alias("student", Student.class);
xstream.alias("note",Note.class);
//字段混叠使用
xstream.aliasField("name",Student.class,"studentName");
//属性混叠使用
xstream.aliasAttribute(Student.class,"studentName","name");
xstream.aliasAttribute(Student.class,"age","age");

或者

xstream.useAttributeFor(Student.class, "studentName");xstream.aliasField("name", Student.class, "studentName");


//隐式集合混叠
xstream.addImplicitCollection(Student.class"notes");

 

结果如下:

 

上面的代码中要去掉类全名,实现属性者都是手动自动配置,是不是觉得有点麻烦呀,接下来,就用注解来实现 上例!

@XStreamAlias("student"//定义类的别名
public class Student {
    @XStreamAlias("name")//定义字段别名
    @XStreamAsAttribute //定义字段是个属性名
    public String studentName;
    @XStreamImplicit //定义集合是个隐式的
    public List<Note> notes new ArrayList<>();
    @XStreamOmitField //定义一个忽略的字段
    private int type;

    public Student(String studentName) {
        this.studentName=studentName;
    }

    public void addNote(Note note) {
        notes.add(note);
    }

    public void setType(int type) {
        this.type=type;
    }

}

 

在Note类名上加上

@XStreamAlias("note")

 

测试

public class XStream_test_4 {

    public static void main(String... args) {
        XStream xStream=new XStream(new DomDriver());
        //通知框架来处理注解
        xStream.processAnnotations(Student.class);
        //或者
//        xStream.autodetectAnnotations(true);
        String xml=xStream.toXML(getSutentDetails());
        System.out.println(XmlUtil.formatXml(xml));
    }

    private static Student getSutentDetails() {
        Student student=new Student("Mans");
        student.addNote(new Note("first","this first name"));
        student.addNote(new Note("second","the second name"));
        student.setType(1);
        return student;
    }
}

 

输出上例相同的结果!

对象流

XStream提供java.io.ObjectInputStream和java.io.ObjectOutputStream替代实现,使对象流可以被序列化或XML序列化。当大对象集要被处理,保持在存储器中的一个对象,这是特别有用的。

语法 : createObjectOutputStream()

ObjectOutputStream objectOutputStream = xstream.createObjectOutputStream(new FileOutputStream("test.txt"));

语法 :createObjectInputStream()

ObjectInputStream objectInputStream = xstream.createObjectInputStream(new FileInputStream("test.txt"));

 

对象流测试代码


public class XStream_test_5 {
    public static void main(String... args) {
        XStream mXStream = new XStream(new DomDriver());
        mXStream.autodetectAnnotations(true);
        Student student1=new Student("ma0","ss0");
        Student student2=new Student("ma1","ss1");
        Student student3=new Student("ma2","ss2");
        Student student4=new Student("ma3","ss3");

        try {
            ObjectOutputStream os=mXStream.createObjectOutputStream(new FileOutputStream("text.txt"));
            os.writeObject(student1);
            os.writeObject(student2);
            os.writeObject(student3);
            os.writeObject(student4);
            os.writeObject("Hello World!");
            os.close();

            ObjectInputStream in=mXStream.createObjectInputStream(new FileInputStream("text.txt"));
            Student student5= (Student) in.readObject();
            Student student6= (Student) in.readObject();
            Student student7= (Student) in.readObject();
            Student student8= (Student) in.readObject();
            String txt= (String) in.readObject();
            System.out.println(student5);
            System.out.println(student6);
            System.out.println(student7);
            System.out.println(student8);
            System.out.println(txt);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}

@XStreamAlias("student")
public class Student {
    private String firstName;
    private String lastName;

    public Student(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return "Student{" +
                "firstName='" firstName '\'+
                ", lastName='" lastName '\'+
                '}';
    }
}

结果如下 :

 

 

Json操作

实体类,还是用上面的Student类

测试代码:

public class XStream_test_6 {
    public static void main(String... args) {
        XStream xStream=new XStream(new JsonHierarchicalStreamDriver(){
            @Override
            public HierarchicalStreamWriter createWriter(Writer out) {
                return new JsonWriter(out, JsonWriter.DROP_ROOT_MODE);
            }
        });

        Student student=new Student("ss","ssss");
        xStream.setMode(XStream.NO_REFERENCES);
        xStream.alias("student",Student.class);
        System.out.println(xStream.toXML(student));
    }
}

结果如下:

 

通过上述例子看XStream在解释xml是非常的方便,转换器主要是能改变xml文件的字段名

更多详解,请看官网

综合例子:

解释如下xml文件:为方便就另保存在 xml.txt文件中

<?xml version="1.0" encoding="utf-8"?>
<alipay>
  <is_success>T</is_success>
  <request>
    <param name="_input_charset">utf-8</param>
    <param name="service">single_trade_query</param>
    <param name="partner">20889010000000</param>
    <param name="out_trade_no">7_20130223150319_26</param>
  </request>
  <response>
    <trade>
      <total_fee>0.01</total_fee>
      <trade_no>2013022356736989</trade_no>
      <trade_status>TRADE_SUCCESS</trade_status>
      <use_coupon>F</use_coupon>
    </trade>
  </response>
  <sign>6c472babf7bd98ascb97fee1666a3303</sign>
  <sign_type>MD5</sign_type>
</alipay>

写实体如下

@XStreamAlias("alipay")
public class Alipay {
    private String is_success;
    private String sign;
    private String sign_type;

    public Request request;
    public Response response;

    @Override
    public String toString() {
        return "Alipay{" +
                "is_success='" is_success '\'+
                ", sign='" sign '\'+
                ", sign_type='" sign_type '\'+
                ", request=" request +
                ", response=" response +
                '}';
    }
}
@XStreamAlias("request")
class Request{
    // @XStreamImplicit(itemFieldName = "param")
    @XStreamImplicit(itemFieldName = "param")
    public List<Param> params;

    public Request(List<Param> params) {
        this.params = params;
    }

    @Override
    public String toString() {
        return "Request{" +
                "param=" params +
                '}';
    }
}
@XStreamAlias("trade")
class Trade{
    private String total_fee;
    private String trade_no;
    private String trade_status;
    private String use_coupon;

    @Override
    public String toString() {
        return "Trade{" +
                "total_fee='" total_fee '\'+
                ", trade_no='" trade_no '\'+
                ", trade_status='" trade_status '\'+
                ", use_coupon='" use_coupon '\'+
                '}';
    }
}

/**
 * ToAttributedValueConverter 取得value
 解释格式 如 <param name="_input_charset">utf-8</param>
 * @XStreamConverter(value=ToAttributedValueConverter.class, strings={"param"})
 * strings={"param"}中的param来接收xmlparam中的值utf-8
 */
//@XStreamAlias("param")
@XStreamConverter(value=ToAttributedValueConverter.class, strings={"param"})
class Param{
    @XStreamAsAttribute()
    private String name;

    public String param;

    @Override
    public String toString() {
        return "Param{" +
                "name='" name '\'+
                ", param='" param '\'+
                '}';
    }
}

@XStreamAlias("response")
class  Response{
    private Trade trade;

    @Override
    public String toString() {
        return "Response{" +
                "trade=" trade +
                '}';
    }
}

测试代码如下:

public class XStrem_alipay {
    public static void main(String... args) {
        try {
            Alipay alipay= XmlUtil.toBeanFromFile("xml.txt",Alipay.class);
            System.out.println(alipay);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意:toBeanFromFile是把xml转换成实体对象的方法,比较简单,综合来看XStream来解释xml是非常的方便,其中要注意的地方是这种 <param name="_input_charset">utf-8</param>

要使用转换器来获取param中的Value,还好框架已实现了,只要在类中加上@XStreamConverter(value=ToAttributedValueConverter.class, strings={"param"})
该注解,一切都变得很容易!!

 

项目代码



来自为知笔记(Wiz)


推荐阅读