一个XML字符串与JAVA对象互转的工具

    近期由于公司业务原因需要调用其他公司的接口,然后格式确实XML字符串的(ke so, 使用json他不香么…).于是自己整理了一个XML和JAVA对象互转的工具,上代码…
   先交代下需要使用到的依赖,这边使用了dom4j的maven jar包。

	<dependency>
		<groupId>dom4j</groupId>
		<artifactId>dom4j</artifactId>
		<version>1.6.1</version>
	</dependency>

   先来一个XML字符串转JAVA对象的方法:

    public static <T> T parseObject(String content, Class<T> clazz) throws Exception {
        Document document = DocumentHelper.parseText(content);
        Element rootElement = document.getRootElement();
        return generateObject(rootElement, clazz);
    }
    private static<T> T generateObject(Element element, Class<T> clazz) throws Exception {
        T instance = clazz.newInstance();
        List<Element> elements = element.elements();
        elements.forEach(e -> doParse(e, instance));
        return instance;
    }

   主要是doPase方法,递归解析XML格式字符:

    private static <T> void doParse(Element element, T instance) {
        String name = element.getName();
        String text = element.getText();
        Class<?> clazz = instance.getClass();
        
        try{
        	// 主要是通过反射获取,设置字段属性,
            Field field = clazz.getDeclaredField(name);
            setAttribute(field, instance, text, element);

            List<Element> elements = element.elements();
            if (!elements.isEmpty()) {
                for (Element ele : elements) {
                    doParse(ele, field);
                }
            }
        }catch(Exception e){
        	// 异常自己处理,偷个懒,嘿嘿...另外为了lambda表达式的美观起见,异常不往外抛了,颜值很重要~
            e.printStackTrace();
        }
    }
    private static<T> void setAttribute(Field field, T obj, String value, Element element) {
        field.setAccessible(true);
        Class<?> fieldType = field.getType();

        try{
            if (fieldType.isAssignableFrom(String.class)) {
                field.set(obj, value);
            } else if (fieldType.isAssignableFrom(Integer.class)) {
                field.set(obj, Integer.parseInt(value));
                // 这里需要添加一些基本类型的转换(手法比较粗糙)
            } else {
                // 如果是自定义的对象,递归。。。
                Object instance = generateObject(element, fieldType);
                field.set(obj, instance);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }

   测试走一把~,交代下测试的JAVA对象,Person对象里面有个City的对象(里面的注解后面会讲到,自己定义,主要是为了JAVA转XML)

@XmlHead(name = "User")
public class Person {

    @XmlProperty(name = "name")
    private String name;
    @XmlProperty(name = "address")
    private String address;
    @XmlProperty(name = "age")
    private Integer age;
    @XmlProperty(name = "city")
    private City city;

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setCity(City city) {
        this.city = city;
    }
}
@XmlHead(name = "city")
public class City {

    @XmlProperty(name = "province")
    private String province;
    @XmlProperty(name = "city")
    private String city;
    @XmlProperty(name = "area")
    private String area;

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getArea() {
        return area;
    }

    public void setArea(String area) {
        this.area = area;
    }
}
    public static void main(String[] args) throws Exception {
        String str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<User>\n" +
                "\t<name>chris</name>\n" +
                "\t<address>shanghai</address>\n" +
                "\t<age>33</age>\n" +
                "\t<city>\n" +
                "\t\t<province>zhejiang</province>\n" +
                "\t\t<city>jiaxing</city>\n" +
                "\t\t<area>海盐</area>\n" +
                "\t</city>\n" +
                "</User>";
        Person person = parseObject(str, Person.class);
    }

   看下效果,可以看到XML格式的字符串成功转成JAVA对象:
在这里插入图片描述
   接着来看下JAVA对象转XML的方法:

    public static <T> String getXmlString(T obj) throws Exception {
        Document doc = DocumentHelper.createDocument();
        Class<?> clazz = obj.getClass();
        XmlHead annotation = clazz.getAnnotation(XmlHead.class);
        String name = annotation.name();
        Element rootEle = doc.addElement(name);
        addSubEle(rootEle, obj);

        String ret = getXmlStringFromDocument(doc, Encoding.UTF_8);
        return ret;
    }
enum Encoding {

        UTF_8("UTF-8"),
        GBK("GBK");

        private String value;

        Encoding(String value) {
            this.value = value;
        }

        public String getValue() {
            return this.value;
        }
    }

   主要的逻辑在addSubEle这个方法里面,往下看:

Class<?> aClass = instance.getClass();
        XmlHead xmlHead = aClass.getDeclaredAnnotation(XmlHead.class);
        // 这个注解是打在类上的,表明这个类下面有子节点
        if (null == xmlHead) {
            return;
        }

        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            XmlProperty xmlProperty = field.getDeclaredAnnotation(XmlProperty.class);
            // 这个注解是打字段上的,用于判断是否解析子节点
            if (null == xmlProperty) {
                continue;
            }
            Class<?> fieldType = field.getType();
            XmlHead head = fieldType.getDeclaredAnnotation(XmlHead.class);
            if (head != null) {
            	// 当前节点下有子节点,向下递归
                Element element = rootEle.addElement(head.name());
                field.setAccessible(true);
                addSubEle(element, field.get(instance));
            } else {
                Element element = rootEle.addElement(xmlProperty.name());
                field.setAccessible(true);
                Object fValue = field.get(instance);
                if (null != fValue) {
                    element.setText(fValue.toString());
                }
            }

   最后把document输出为字符串:

public static String getXmlStringFromDocument(Document document, Encoding encoding) {
        StringWriter sw = new StringWriter();
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding(encoding.getValue());

        try {

            XMLWriter xmlWriter = new XMLWriter(sw, format);
            xmlWriter.write(document);
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                sw.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return sw.toString();
    }

   自定义注解如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface XmlHead {
    String name();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface XmlProperty {
    String name();
}

   最后再测试一下~

        Person person = new Person();
        person.setName("chris");
        person.setAge(33);
        person.setAddress("shanghai");
        City city = new City();
        city.setProvince("zhejiang");
        city.setCity("jiaxing");
        city.setArea("haiyan");
        person.setCity(city);
        String xmlString = getXmlString(person);
        System.out.println(xmlString);

   结果如下:
在这里插入图片描述

小结

   主要使用了反射加递归的思路写了一个小工具完成XML格式字符串和JAVA对象的相互转换,对于JAVA对象字段的属性类型判断比较粗糙,有待优化(属性名字需要和XML节点的值相同)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值