对象和xml之间的转化--XStream的使用

对象和xml之间的转化

在项目开发中有时候与其他第三方接口对接需要用到,参数和响应有时候会以xml的形式传递

需要导入的依赖是 pom

        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.10</version>
        </dependency>

相关工具类的

XStreamFactory

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.naming.NameCoder;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDomDriver;
import com.thoughtworks.xstream.security.AnyTypePermission;

import java.io.Writer;
import java.lang.reflect.Field;

public class XStreamFactory {
    public static final String CDATA_PREFIX = "<![CDATA[";
    public static final String CDATA_SUFFIX = "]]>";
    public static XStream getXStream() {
        final NameCoder nameCoder = new NoNameCoder();
        XStream xStream = new XStream(new XppDomDriver(nameCoder) {
            @Override
            public HierarchicalStreamWriter createWriter(Writer out) {
                return new PrettyPrintWriter(out, nameCoder) {
                    boolean cdataFlag = false;
                    Class<?> targetClass = null;
                    @Override
                    public void startNode(String name, Class clazz) {
                        super.startNode(name, clazz);
                        if (targetClass == null) {
                            targetClass = clazz;
                        }
                        cdataFlag = isCDATA(targetClass, name);
                    }
                    @Override
                    public void writeText(QuickWriter writer, String text) {
                        if (cdataFlag) {
                            writer.write(CDATA_PREFIX);
                            writer.write(text);
                            writer.write(CDATA_SUFFIX);
                        } else {
                            writer.write(text);
                        }
                    }
                };
            }
        });

        // 设置默认的安全校验
        XStream.setupDefaultSecurity(xStream);
        // 使用本地的类加载器
        xStream.setClassLoader(XmlUtils.class.getClassLoader());
        // 允许所有的类进行转换
        xStream.addPermission(AnyTypePermission.ANY);
        return xStream;
    }
    private static boolean isCDATA(Class<?> clazz, String fieldAlias) {
        //检查类本身
        boolean cdataFlag = isExistCDATA(clazz, fieldAlias);
        if (cdataFlag) {
            return cdataFlag;
        }
        //继续检查父类
        Class<?> superClazz = clazz.getSuperclass();
        while (!superClazz.equals(Object.class)) {
            cdataFlag = isExistCDATA(superClazz, fieldAlias);
            if (cdataFlag) {
                return cdataFlag;
            }
            superClazz = superClazz.getClass().getSuperclass();
        }
        return false;
    }
    /**
     * 检查是否有 @XStreamCDATA 注解
     * @param clazz clazz
     * @param fieldAlias fieldAlias
     * @return
     */
    private static boolean isExistCDATA(Class<?> clazz, String fieldAlias) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.getAnnotation(XStreamCDATA.class) != null) {
                XStreamAlias xStreamAlias = field.getAnnotation(XStreamAlias.class);
                if (xStreamAlias != null && fieldAlias.equals(xStreamAlias.value())) {
                    return true;
                } else {
                    if (fieldAlias.equals(field.getName())) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}

XStreamCDATA 这个注解是为了处理xml的内容需要添加<![CDATA[]>

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface XStreamCDATA {
}

XmlUtils


import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.mapper.MapperWrapper;
import com.thoughtworks.xstream.security.AnyTypePermission;
import org.apache.commons.lang3.StringUtils;

public class XmlUtils {
    private static String XML_TAG = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
    private static final String OBJ = "obj";

    private static final XStream xStream = XStreamFactory.getXStream();

    /**
     * 对象转xml
     *
     * @param obj 对象
     * @return
     */
    public static String toXml(Object obj) {
        xStream.processAnnotations(obj.getClass());
        //如果生成的是Objec不显示class属性
        xStream.aliasSystemAttribute(null, "class");
        return XML_TAG + xStream.toXML(obj);
    }
     /**
     * 定制化需求 特殊处理XStream对象
     * @return
     */
    private static XStream getInstance() {
        XStream xStream = new XStream(new DomDriver("UTF-8")) {
            /**
             * 忽略xml中多余字段
             */
            @Override
            protected MapperWrapper wrapMapper(MapperWrapper next) {
                return new MapperWrapper(next) {
                    @SuppressWarnings("rawtypes")
                    @Override
                    public boolean shouldSerializeMember(Class definedIn, String fieldName) {
                        if (definedIn == Object.class) {
                            return false;
                        }
                        return super.shouldSerializeMember(definedIn, fieldName);
                    }
                };
            }
        };

        // 设置默认的安全校验
        XStream.setupDefaultSecurity(xStream);
        // 使用本地的类加载器
        xStream.setClassLoader(XmlUtils.class.getClassLoader());
        // 允许所有的类进行转换
        xStream.addPermission(AnyTypePermission.ANY);
        return xStream;
    }
    
    /**
     * xml 转 bean
     *
     * @param xml
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T xmlToBean(String xml, Class<T> clazz) {
        XStream instance = getInstance();
        instance.processAnnotations(clazz);
        instance.autodetectAnnotations(true);
        T obj = (T) instance.fromXML(xml);
        return obj;
    }
    
}

测试对象

TestDemo


import com.gyjx.outgateway.modle.request.UserNumber;
import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias("root")
public class TestDemo {

    @XStreamAlias("UserNumber")
    private String userNumber;

    @XStreamAlias("name")
  //  @XStreamCDATA
    private String name;

    @XStreamAlias("Record")
    private UserNumber record;


    public TestDemo() {
    }

    public String getUserNumber() {
        return userNumber;
    }

    public void setUserNumber(String userNumber) {
        this.userNumber = userNumber;
    }

    public String getName() {
        return name;
    }

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

    public UserNumber getRecord() {
        return record;
    }

    public void setRecord(UserNumber record) {
        this.record = record;
    }

    @Override
    public String toString() {
        return "TestDemo{" +
                "userNumber='" + userNumber + '\'' +
                ", name='" + name + '\'' +
                ", record=" + record +
                '}';
    }
}

UserNumber


import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias("Record")
public class UserNumber {

    @XStreamAlias("UserNumber")
    private String userNumber;

    public UserNumber() {
    }

    public String getUserNumber() {
        return userNumber;
    }

    public void setUserNumber(String userNumber) {
        this.userNumber = userNumber;
    }

    @Override
    public String toString() {
        return "UserNumber{" +
                "userNumber='" + userNumber + '\'' +
                '}';
    }
}

对象与xml相互转化


    @Test
    public void testXml(){

        TestDemo testDemo = new TestDemo();
        testDemo.setName("qiuwei");
        testDemo.setUserNumber("13298878771");
        
        UserNumber userNumber = new UserNumber();
        userNumber.setUserNumber("17611013092");
        testDemo.setRecord(userNumber);

        //对象-->xml
        String s = XmlUtils.toXml(testDemo);
        System.out.println(s);

        System.out.println("===============================");
        //xml-->对象
        TestDemo testDemo1 = XmlUtils.xmlToBean(s, TestDemo.class);

        System.out.println(testDemo1.toString());
    }

测试结果
在这里插入图片描述

如何优雅处理<![CDATA[]>

在需要转化的属性上添加 @XStreamCDATA 注解
在这里插入图片描述

测试结果

在这里插入图片描述

当然 处理<![CDATA[]> 还有其他方式这里的工具类已经集成的处理方式,大家可以根据自己的项目需求进行集成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值