Xstream使用及注解

构造

package com.shunnengnet.infra.util;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class XstreamUtils {

    /**
     * 将bean转换为xml
     *
     * @param obj 转换的bean
     * @return bean转换为xml
     */
    public static String toXml(Object obj) {
        XStream xStream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("_-", "_")));

        //xstream使用注解转换
        xStream.processAnnotations(obj.getClass());
        xStream.allowTypeHierarchy(obj.getClass());
        xStream.autodetectAnnotations(true);
        String xml = xStream.toXML(obj);
        return xml.replace("&amp;", "&").replace("&quot;", "\"").replace("&lt;", "<")
            .replace("&gt;", ">").replace("&apos;", "'");
    }

    /**
     * 将xml转换为bean
     *
     * @param <T> 泛型
     * @param xml 要转换为bean的xml
     * @param cls bean对应的Class
     * @return xml转换为bean
     */
    public static <T> T toObject(String xml, Class<T> cls) {
        XStream xstream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("_-", "_")));

        //xstream使用注解转换
        xstream.processAnnotations(cls);
        xstream.allowTypeHierarchy(cls);
        xstream.autodetectAnnotations(true);
        return cls.cast(xstream.fromXML(xml));
    }

    /**
     * xml转成映射好的实体
     * @param xml xml字符
     * @param cl 类
     * @param classes 多层嵌套的类的数组
     * @param <T> 类的类型
     * @return <T> T 返回需要的类型
     */
    public static <T> T toObject(String xml, Class<T> cl, Class<?>[] classes) {
        XStream xstream = new XStream(new DomDriver("UTF_8", new XmlFriendlyNameCoder("-_", "_")));
        xstream.processAnnotations(cl);
        if (null == classes || classes.length == 0) {
            xstream.allowTypeHierarchy(cl);
        } else {
            xstream.allowTypes(classes);
        }
        xstream.autodetectAnnotations(true);
        return cl.cast(xstream.fromXML(xml));
    }

    /**
     * 对象转成映射好的xml字符
     * @param obj 对象
     * @return 最终xml
     */
    public static String toXmlNoReplace(Object obj) {
        XStream xStream = new XStream(new DomDriver("UTF_8", new XmlFriendlyNameCoder("-_", "_")));
        xStream.processAnnotations(obj.getClass());
        xStream.allowTypeHierarchy(obj.getClass());
        xStream.autodetectAnnotations(true);
        return xStream.toXML(obj);
    }
}

自定义转换器

@XStreamConverter(value = CdataConverter.class)


public class CdataConverter implements Converter {

   @Override
   public boolean canConvert(Class type) {
       return String.class.isAssignableFrom(type);
   }

    @Override
    public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext marshallingContext) {
        String cData = (String) o;
        writer.setValue("<![CDATA["+cData+"]]"+">");
    }

    /**
    * Convert textual data back into an object.
    *
    * @param reader  The stream to read the text from.
    * @param context
    * @return The resulting object.
    */
   @Override
   public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
       return reader.getValue();
   }
}

//自带的转换器,将text之外的属性定义为节点的属性,text为该节点的值
@XStreamConverter(value = ToAttributedValueConverter.class,strings = {“text”})

使用实例

Address

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@XStreamAlias("_Address")
public class Address implements Serializable {


    private static final long serialVersionUID = -2204135694698262519L;

    @XStreamAlias("_Country")
    private String country;

    @XStreamAlias("_Province")
    private String province;

    @XStreamAlias("_City")
    @XStreamConverter(value = CdataConverter.class)
    private String city;

}

Person

@ToString
@XStreamAlias("Person")
@AllArgsConstructor
@NoArgsConstructor
public class Person implements Serializable {


    private static final long serialVersionUID = 8703644148766584973L;

    @XStreamAsAttribute
    private String type;

    /**
     * XStreamOmitField 忽略此属性
     */
    @XStreamOmitField
    private String id;

    /**
     * XmlElment实体主要是为了方便在该标签上添加属性
     */
    @XStreamAlias("_Name")
    private XmlElement name;

    /**
     * 定义属性别名
     */
    @XStreamAlias("_Sex")
    private String sex;


    @XStreamAlias("_Age")
    private int age;

    @XStreamAlias("_Addresses")
   // @XStreamImplicit // 去除根标签  addresses
    private List<Address> addresses;


}

XmlElement 属性及节点值

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
//自带的转换器,将text之外的属性定义为节点的属性,text为该节点的值
@XStreamConverter(value = ToAttributedValueConverter.class,strings = {"text"})
public class XmlElement implements Serializable {


    private static final long serialVersionUID = 6490005123023660218L;

    private String attribute;

    private String text;

}

执行样例

 @Test
    void contextLoads() {
        XStream xStream = new XStream(new DomDriver("UTF_8",
                new XmlFriendlyNameCoder("-_", "_")));
        //自动注解扫描,否则注解不生效
        xStream.autodetectAnnotations(true);
        List<Address> list = new ArrayList<>();
        list.add(new Address("China", "ShanDong", "JiNan"));
        list.add(new Address("China", "ShanDong", "LiaoCheng"));
        Person person = new Person("中国人","1", new XmlElement("中文名", "汤姆"), "Male", 18,list);
        log.info("实体信息:{}",person);
        String s = xStream.toXML(person);
        String sTo = XStreamUtils.toXml(person);
        log.info("转换的xml:{}",s);
        log.info("转换的xml:{}",sTo);
        log.error("转换的xml-转义后:{}", StringEscapeUtils.unescapeXml(sTo));
    }

    @Test
    public void test01(){
        String xml =
                "<?xml version=\"1.0\" encoding=\"GBK\"?>\n" +
                "<Person type=\"中国人\">\n" +
                "  <_Name attribute=\"中文名\">汤姆</_Name>\n" +
                "  <_Sex>Male</_Sex>\n" +
                "  <_Age>18</_Age>\n" +
                "  <_Addresses>\n" +
                "    <_Address>\n" +
                "      <_Country>China</_Country>\n" +
                "      <_Province>ShanDong</_Province>\n" +
                "      <_City>JiNan</_City>\n" +
                "    </_Address>\n" +
                "    <_Address>\n" +
                "      <_Country>China</_Country>\n" +
                "      <_Province>ShanDong</_Province>\n" +
                "      <_City>LiaoCheng</_City>\n" +
                "    </_Address>\n" +
                "  </_Addresses>\n" +
                "</Person>";
                /*"<?xml version=\"1.0\" encoding=\"GBK\"?>\n" +
                "<Person type=\"中国人\">\n" +
                "  <_Name attribute=\"中文名\">汤姆</_Name>\n" +
                "  <_Sex>Male</_Sex>\n" +
                "  <_Age>18</_Age>\n" +
                "  <_Addresses>\n" +
                "    <_Address>\n" +
                "      <_Country>China</_Country>\n" +
                "      <_Province>ShanDong</_Province>\n" +
                "      <_City>JiNan</_City>\n" +
                "    </_Address>\n" +
                "    <_Address>\n" +
                "      <_Country>China</_Country>\n" +
                "      <_Province>ShanDong</_Province>\n" +
                "      <_City>LiaoCheng</_City>\n" +
                "    </_Address>\n" +
                "  </_Addresses>\n" +
                "</Person>";*/
        XStream xStream = new XStream(new DomDriver("UTF_8",
                new XmlFriendlyNameCoder("-_", "_")));
        xStream.processAnnotations(Person.class);
        xStream.autodetectAnnotations(true);
        //com.thoughtworks.xstream.security.ForbiddenClassException 报错解决
        //1.
        Class<?>[] classes = new Class[]{Person.class,Address.class};
//        xStream.allowTypes(classes);
        //2.
//        xStream.allowTypeHierarchy(Person.class);
//        xStream.allowTypeHierarchy(Address.class);
        Person person = XStreamUtils.toObject(xml,Person.class,classes);
        //如果没有嵌套  执行 XStreamUtils.toObject(xml,Person.class,null);
//        Person person = (Person)xStream.fromXML(xml);
        log.info("翻转实体:{}",person);
    }

}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值