JAVA对象转xml(支持递归生成复杂数据类型)

JAVA对象转xml(支持递归生成复杂数据类型)_第1张图片

 

前言

调用一些soap协议的项目你或许使用的到,也许我是在造轮子,但是我没在网上找到合适的轮子,就根据现有的项目自己造了一个,废话不说,说思路

使用反射获取对象的属性,根据属性的类型做出相应的处理,如果为基本类型直接使用dom4j创建节点赋值,如果遇到的集合递归处理集合中的对象,并生成相应的节点

自定义了几个注解处理相应的 标签别名、根对象别名、属性为集合类型的别名

先引入依赖

        
            org.dom4j
            dom4j
            2.1.1
        

项目背景,调用soap协议的项目,但是xml参数有点和想想中的不一样,下面看一下

JAVA对象转xml(支持递归生成复杂数据类型)_第2张图片

属性大部分都是下划线命名;

如果你直接创建的java对象也使用这样的命名,然后使用 dom4j的Document也能生成,但是以前学习的时候 命名规范是不是驼峰命名法

代码

自定义注解

package com.zxw.xml.annotation;

import java.lang.annotation.*;

/**
 * @author zhangxuewei
 * @description 标签内的属性注解
 * @date 2023/7/6 17:08
 */
@Target({ElementType.TYPE,ElementType.FIELD})//@Target其中参数类型是ElementType[]数组,其中ElementType是枚举类型
@Retention(RetentionPolicy.RUNTIME)//@Retention 表明该注解的生命周期,其中RetentionPolicy 是枚举类型
@Documented//表明该注解标记的元素可以被Javadoc 或类似的工具文档化
public @interface XmlAttributeName {
    String tagName() default "";// 标签名称
}
package com.zxw.xml.annotation;

import java.lang.annotation.*;

/**
 * @author zhangxuewei
 * @description 标签根对象的 标签别名 注解
 * @date 2023/7/6 17:07
 */
@Target({ElementType.TYPE})//@Target其中参数类型是ElementType[]数组,其中ElementType是枚举类型
@Retention(RetentionPolicy.RUNTIME)//@Retention 表明该注解的生命周期,其中RetentionPolicy 是枚举类型
@Documented//表明该注解标记的元素可以被Javadoc 或类似的工具文档化
public @interface XmlRootElementName {
    String tagName() default "";// 标签名称

}
package com.zxw.xml.annotation;

import java.lang.annotation.*;

/**
 * @author zhangxuewei
 * @description 对象属性的标签别名注解
 * @date 2023/7/6 17:09
 */
@Target({ElementType.TYPE,ElementType.FIELD})//@Target其中参数类型是ElementType[]数组,其中ElementType是枚举类型
@Retention(RetentionPolicy.RUNTIME)//@Retention 表明该注解的生命周期,其中RetentionPolicy 是枚举类型
@Documented//表明该注解标记的元素可以被Javadoc 或类似的工具文档化
public @interface XmlTagName {
    String tagName() default "";// 标签名称

    /**
     * 如果属性为List,需要在集合对象追加标签名称,使用这个属性
     *
     * 使用样例
     *  public class SyncNcRecSettleBIillVO {
     *     @XmlTagName(tagName = "items", arrayObjTagName = "item")
     *     private List items;
     *     ....
     *  }
     *
     *  
     *       
     *          
     *          
     *          
     *       
     *       
     *          
     *          
     *          
     *        
     *  
     * @return
     */
    String arrayObjTagName() default "";
}

需要生成xml的java对象

package com.zxw.xml.domain.vo;

import com.zxw.xml.annotation.XmlAttributeName;
import com.zxw.xml.annotation.XmlRootElementName;
import com.zxw.xml.annotation.XmlTagName;

/**
 * @projectName: ruoyi
 * @package: com.ruoyi.bmp.fi.domain.vo
 * @className: SyncNcUfinterface
 * @author: zhangxuewei
 * @description: TODO
 * @date: 2023/7/6 13:57
 * @version: 1.0
 */
@XmlRootElementName(tagName = "ufinterface")
public class SyncNcUfinterface {

    @XmlAttributeName(tagName = "account")
    private String account = "develop";

    @XmlAttributeName(tagName = "billtype")
    private String billtype;

    @XmlAttributeName(tagName = "filename")
    private String filename;

    @XmlAttributeName(tagName = "groupcode")
    private String groupcode;

    @XmlAttributeName(tagName = "isexchange")
    private String isexchange = "Y";

    @XmlAttributeName(tagName = "replace")
    private String replace = "Y";

    @XmlAttributeName(tagName = "roottag")
    private String roottag;

    @XmlAttributeName(tagName = "sender")
    private String sender;

    @XmlTagName(tagName = "bill")
    private Bill bill;

    public String getAccount() {
        return account;
    }

    public SyncNcUfinterface setAccount(String account) {
        this.account = account;
        return this;
    }

    public String getBilltype() {
        return billtype;
    }

    public SyncNcUfinterface setBilltype(String billtype) {
        this.billtype = billtype;
        return this;
    }

    public String getFilename() {
        return filename;
    }

    public SyncNcUfinterface setFilename(String filename) {
        this.filename = filename;
        return this;
    }

    public String getGroupcode() {
        return groupcode;
    }

    public SyncNcUfinterface setGroupcode(String groupcode) {
        this.groupcode = groupcode;
        return this;
    }

    public String getIsexchange() {
        return isexchange;
    }

    public SyncNcUfinterface setIsexchange(String isexchange) {
        this.isexchange = isexchange;
        return this;
    }

    public String getReplace() {
        return replace;
    }

    public SyncNcUfinterface setReplace(String replace) {
        this.replace = replace;
        return this;
    }

    public String getRoottag() {
        return roottag;
    }

    public SyncNcUfinterface setRoottag(String roottag) {
        this.roottag = roottag;
        return this;
    }

    public String getSender() {
        return sender;
    }

    public SyncNcUfinterface setSender(String sender) {
        this.sender = sender;
        return this;
    }

    public Bill getBill() {
        return bill;
    }

    public Bill setBill(Object ob) {
        this.bill = new Bill();
        this.bill.setObject(ob);
        return this.bill;
    }

    class Bill {

        @XmlTagName(tagName = "billhead")
        private Object object;

        @XmlAttributeName(tagName = "id")
        private String id;

        public Object getObject() {
            return object;
        }

        public void setObject(Object object) {
            this.object = object;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }
    }
}
package com.zxw.xml.domain.vo;

import com.zxw.xml.annotation.XmlAttributeName;
import com.zxw.xml.annotation.XmlRootElementName;
import com.zxw.xml.annotation.XmlTagName;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * @projectName: ruoyi
 * @package: com.ruoyi.bmp.fi.domain.vo
 * @className: SyncncRecSettleBIillVO
 * @author: zhangxuewei
 * @description: 同步nc首款结算单VO
 * @date: 2023/7/6 10:06
 * @version: 1.0
 */
public class SyncNcRecSettleBIillVO {

    // 单据日期
    @XmlTagName(tagName = "bill_date")
    private Date billDate;

    // 制单人
    private String billmaker;

    // 制单日期
    @XmlTagName(tagName = "billmaker_date")
    private Date billmakerDate;

    // 创建人
    private String creator;

    // 币种
    @XmlTagName(tagName = "pk_currtype")
    private String pkCurrtype;

    // 所属集团
    @XmlTagName(tagName = "pk_group")
    private String pkGroup;

    // 结算财务组织
    @XmlTagName(tagName = "pk_org")
    private String pkOrg;

    @XmlTagName(tagName = "items", arrayObjTagName = "item")
    private List items;

    public static class RecSettleBIillDetail {

        // 单据分录编号
        @XmlTagName(tagName = "billdetail_no")
        private String billdetailNo;

        // 摘要
        private String memo;

        // 收款银行账户
        @XmlTagName(tagName = "pk_account")
        private String pkAccount;

        // 所属集团
        @XmlTagName(tagName = "pk_group")
        private String pkGroup;

        // 结算财务组织
        @XmlTagName(tagName = "pk_org")
        private String pkOrg;

        // 收支项目
        @XmlTagName(tagName = "pk_recproject")
        private String pkRecproject;

        // 收款原币金额
        @XmlTagName(tagName = "rec_primal")
        private BigDecimal recPrimal;

        public String getBilldetailNo() {
            return billdetailNo;
        }

        public void setBilldetailNo(String billdetailNo) {
            this.billdetailNo = billdetailNo;
        }

        public String getMemo() {
            return memo;
        }

        public void setMemo(String memo) {
            this.memo = memo;
        }

        public String getPkAccount() {
            return pkAccount;
        }

        public void setPkAccount(String pkAccount) {
            this.pkAccount = pkAccount;
        }
    }

    public Date getBillDate() {
        return billDate;
    }

    public void setBillDate(Date billDate) {
        this.billDate = billDate;
    }

    public String getBillmaker() {
        return billmaker;
    }

    public void setBillmaker(String billmaker) {
        this.billmaker = billmaker;
    }

    public Date getBillmakerDate() {
        return billmakerDate;
    }

    public void setBillmakerDate(Date billmakerDate) {
        this.billmakerDate = billmakerDate;
    }

    public String getCreator() {
        return creator;
    }

    public void setCreator(String creator) {
        this.creator = creator;
    }

    public String getPkCurrtype() {
        return pkCurrtype;
    }

    public void setPkCurrtype(String pkCurrtype) {
        this.pkCurrtype = pkCurrtype;
    }

    public String getPkGroup() {
        return pkGroup;
    }

    public void setPkGroup(String pkGroup) {
        this.pkGroup = pkGroup;
    }

    public String getPkOrg() {
        return pkOrg;
    }

    public void setPkOrg(String pkOrg) {
        this.pkOrg = pkOrg;
    }

    public List getItems() {
        return items;
    }

    public void setItems(List items) {
        this.items = items;
    }
}

工具类

package com.zxw.xml.util;

import cn.hutool.core.date.DateUtil;
import com.zxw.xml.annotation.XmlAttributeName;
import com.zxw.xml.annotation.XmlRootElementName;
import com.zxw.xml.annotation.XmlTagName;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @projectName: ruoyi
 * @package: com.ruoyi.common.utils.xml
 * @className: ObjectToXmlConverter
 * @author: zhangxuewei
 * @description: TODO
 * @date: 2023/7/6 13:15
 * @version: 1.0
 */
public class ObjectToXmlConverter {
    public static String convertToXml(Object object) {
        Document document = DocumentHelper.createDocument();
        XmlRootElementName an = object.getClass().getDeclaredAnnotation(XmlRootElementName.class);
        Element rootElement = document.addElement(ObjectUtils.isEmpty(an.tagName()) ? object.getClass().getSimpleName() : an.tagName());
        convertObjectToElements(object, rootElement, document);
        return document.asXML();
    }

    private static void convertObjectToElements(Object object, Element parentElement, Document document) {
        for (Field field : object.getClass().getDeclaredFields()) {
            try {
                field.setAccessible(true);
                Object value = field.get(object);
                // 如果为空,给个空字符串,这样即使 属性为null 也会生成标签
                if (value == null) {
                    value = "";
                }
                if (!(field.getName().indexOf("this") > -1)) {
                    if (!ObjectUtils.isEmpty(field.getAnnotation(XmlAttributeName.class))) {
                        parentElement.addAttribute(ObjectUtils.isEmpty(field.getAnnotation(XmlAttributeName.class)) ? field.getName() : field.getAnnotation(XmlAttributeName.class).tagName(), value.toString());
                    } else {
                        Element element = parentElement.addElement(ObjectUtils.isEmpty(field.getAnnotation(XmlTagName.class)) ? field.getName() : field.getAnnotation(XmlTagName.class).tagName());
                        if (value instanceof String || value instanceof Integer || value instanceof Boolean || value instanceof Long || value instanceof BigDecimal) {
                            element.setText(String.valueOf(value));
                        } else if (value instanceof Double || value instanceof Float) {
                            element.setText(Double.toString(Double.valueOf(value.toString())));
                        } else if (value instanceof Date) {
                            element.setText(DateUtil.format((Date) value, "yyyy-MM-dd HH:mm:ss"));
                        } else if (value instanceof List) {
                            for (Object listValue : (List) value) {
                                Element elementL;
                                if (!ObjectUtils.isEmpty(field.getAnnotation(XmlTagName.class)) && !ObjectUtils.isEmpty(field.getAnnotation(XmlTagName.class).arrayObjTagName()))
                                    elementL = element.addElement(field.getAnnotation(XmlTagName.class).arrayObjTagName());
                                else
                                    elementL = element.addElement("item");
                                convertObjectToElements(listValue, elementL, document);
                            }
                        } else if (value instanceof Map) {
                            for (Map.Entry mapEntry : ((Map) value).entrySet()) {
                                Element mapElement = element.addElement(mapEntry.getKey());
                                convertObjectToElements(mapEntry.getValue(), mapElement, document);
                            }
                        } else {
                            convertObjectToElements(value, element, document);
                        }
                    }
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (NullPointerException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

测试

package com.zxw.xml.test;

import com.zxw.xml.domain.vo.SyncNcRecSettleBIillVO;
import com.zxw.xml.domain.vo.SyncNcUfinterface;
import com.zxw.xml.util.ObjectToXmlConverter;
import org.apache.tools.ant.util.DateUtils;

import java.util.ArrayList;
import java.util.Date;

/**
 * @projectName: util-cloud
 * @package: com.zxw.xml.test
 * @className: Test
 * @author: zhangxuewei
 * @description: TODO
 * @date: 2023/7/6 17:07
 * @version: 1.0
 */
public class Test {
    public static void main(String[] args) {
        SyncNcRecSettleBIillVO s = new SyncNcRecSettleBIillVO();
        s.setBillDate(new Date());
        s.setPkCurrtype("10001kjhhj1232321");
        s.setItems(new ArrayList() {{
            SyncNcRecSettleBIillVO.RecSettleBIillDetail detail = new SyncNcRecSettleBIillVO.RecSettleBIillDetail();
            SyncNcRecSettleBIillVO.RecSettleBIillDetail detail2 = new SyncNcRecSettleBIillVO.RecSettleBIillDetail();
            add(detail);
            add(detail2);
        }});
        SyncNcUfinterface syncNcUfinterface = new SyncNcUfinterface();
        syncNcUfinterface.setBilltype("RecSettleBillFromBmp").setSender("Bmp").setBill(s);

        System.out.println(ObjectToXmlConverter.convertToXml(syncNcUfinterface));
    }

}

测试结果

D:\mcdev\jdk8\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:53019,suspend=y,server=n -javaagent:C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2020.1\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "D:\mcdev\jdk8\jre\lib\charsets.jar;D:\mcdev\jdk8\jre\lib\deploy.jar;D:\mcdev\jdk8\jre\lib\ext\access-bridge-64.jar;D:\mcdev\jdk8\jre\lib\ext\cldrdata.jar;D:\mcdev\jdk8\jre\lib\ext\dnsns.jar;D:\mcdev\jdk8\jre\lib\ext\jaccess.jar;D:\mcdev\jdk8\jre\lib\ext\jfxrt.jar;D:\mcdev\jdk8\jre\lib\ext\localedata.jar;D:\mcdev\jdk8\jre\lib\ext\nashorn.jar;D:\mcdev\jdk8\jre\lib\ext\sunec.jar;D:\mcdev\jdk8\jre\lib\ext\sunjce_provider.jar;D:\mcdev\jdk8\jre\lib\ext\sunmscapi.jar;D:\mcdev\jdk8\jre\lib\ext\sunpkcs11.jar;D:\mcdev\jdk8\jre\lib\ext\zipfs.jar;D:\mcdev\jdk8\jre\lib\javaws.jar;D:\mcdev\jdk8\jre\lib\jce.jar;D:\mcdev\jdk8\jre\lib\jfr.jar;D:\mcdev\jdk8\jre\lib\jfxswt.jar;D:\mcdev\jdk8\jre\lib\jsse.jar;D:\mcdev\jdk8\jre\lib\management-agent.jar;D:\mcdev\jdk8\jre\lib\plugin.jar;D:\mcdev\jdk8\jre\lib\resources.jar;D:\mcdev\jdk8\jre\lib\rt.jar;C:\workspace\program\util-cloud\target\classes;C:\workspace\mavenRepository\org\springframework\boot\spring-boot-starter-web\2.7.9\spring-boot-starter-web-2.7.9.jar;C:\workspace\mavenRepository\org\springframework\boot\spring-boot-starter\2.7.9\spring-boot-starter-2.7.9.jar;C:\workspace\mavenRepository\org\springframework\boot\spring-boot\2.7.9\spring-boot-2.7.9.jar;C:\workspace\mavenRepository\org\springframework\boot\spring-boot-autoconfigure\2.7.9\spring-boot-autoconfigure-2.7.9.jar;C:\workspace\mavenRepository\org\springframework\boot\spring-boot-starter-logging\2.7.9\spring-boot-starter-logging-2.7.9.jar;C:\workspace\mavenRepository\ch\qos\logback\logback-classic\1.2.11\logback-classic-1.2.11.jar;C:\workspace\mavenRepository\ch\qos\logback\logback-core\1.2.11\logback-core-1.2.11.jar;C:\workspace\mavenRepository\org\apache\logging\log4j\log4j-to-slf4j\2.17.2\log4j-to-slf4j-2.17.2.jar;C:\workspace\mavenRepository\org\apache\logging\log4j\log4j-api\2.17.2\log4j-api-2.17.2.jar;C:\workspace\mavenRepository\org\slf4j\jul-to-slf4j\1.7.36\jul-to-slf4j-1.7.36.jar;C:\workspace\mavenRepository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;C:\workspace\mavenRepository\org\yaml\snakeyaml\1.30\snakeyaml-1.30.jar;C:\workspace\mavenRepository\org\springframework\boot\spring-boot-starter-json\2.7.9\spring-boot-starter-json-2.7.9.jar;C:\workspace\mavenRepository\com\fasterxml\jackson\core\jackson-databind\2.13.5\jackson-databind-2.13.5.jar;C:\workspace\mavenRepository\com\fasterxml\jackson\core\jackson-annotations\2.13.5\jackson-annotations-2.13.5.jar;C:\workspace\mavenRepository\com\fasterxml\jackson\core\jackson-core\2.13.5\jackson-core-2.13.5.jar;C:\workspace\mavenRepository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.13.5\jackson-datatype-jdk8-2.13.5.jar;C:\workspace\mavenRepository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.13.5\jackson-datatype-jsr310-2.13.5.jar;C:\workspace\mavenRepository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.13.5\jackson-module-parameter-names-2.13.5.jar;C:\workspace\mavenRepository\org\springframework\boot\spring-boot-starter-tomcat\2.7.9\spring-boot-starter-tomcat-2.7.9.jar;C:\workspace\mavenRepository\org\apache\tomcat\embed\tomcat-embed-core\9.0.71\tomcat-embed-core-9.0.71.jar;C:\workspace\mavenRepository\org\apache\tomcat\embed\tomcat-embed-el\9.0.71\tomcat-embed-el-9.0.71.jar;C:\workspace\mavenRepository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.71\tomcat-embed-websocket-9.0.71.jar;C:\workspace\mavenRepository\org\springframework\spring-web\5.3.25\spring-web-5.3.25.jar;C:\workspace\mavenRepository\org\springframework\spring-beans\5.3.25\spring-beans-5.3.25.jar;C:\workspace\mavenRepository\org\springframework\spring-webmvc\5.3.25\spring-webmvc-5.3.25.jar;C:\workspace\mavenRepository\org\springframework\spring-aop\5.3.25\spring-aop-5.3.25.jar;C:\workspace\mavenRepository\org\springframework\spring-context\5.3.25\spring-context-5.3.25.jar;C:\workspace\mavenRepository\org\springframework\spring-expression\5.3.25\spring-expression-5.3.25.jar;C:\workspace\mavenRepository\mysql\mysql-connector-java\8.0.25\mysql-connector-java-8.0.25.jar;C:\workspace\mavenRepository\com\google\protobuf\protobuf-java\3.11.4\protobuf-java-3.11.4.jar;C:\workspace\mavenRepository\org\projectlombok\lombok\1.18.26\lombok-1.18.26.jar;C:\workspace\mavenRepository\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;C:\workspace\mavenRepository\org\springframework\spring-core\5.3.25\spring-core-5.3.25.jar;C:\workspace\mavenRepository\org\springframework\spring-jcl\5.3.25\spring-jcl-5.3.25.jar;C:\workspace\mavenRepository\org\jsoup\jsoup\1.13.1\jsoup-1.13.1.jar;C:\workspace\mavenRepository\org\apache\poi\poi\3.10-beta2\poi-3.10-beta2.jar;C:\workspace\mavenRepository\commons-codec\commons-codec\1.15\commons-codec-1.15.jar;C:\workspace\mavenRepository\org\apache\poi\poi-ooxml\3.10-beta2\poi-ooxml-3.10-beta2.jar;C:\workspace\mavenRepository\dom4j\dom4j\1.6.1\dom4j-1.6.1.jar;C:\workspace\mavenRepository\xml-apis\xml-apis\1.0.b2\xml-apis-1.0.b2.jar;C:\workspace\mavenRepository\org\apache\poi\poi-ooxml-schemas\3.10-beta2\poi-ooxml-schemas-3.10-beta2.jar;C:\workspace\mavenRepository\org\apache\xmlbeans\xmlbeans\2.3.0\xmlbeans-2.3.0.jar;C:\workspace\mavenRepository\stax\stax-api\1.0.1\stax-api-1.0.1.jar;C:\workspace\mavenRepository\org\apache\poi\poi-scratchpad\3.0.2-FINAL\poi-scratchpad-3.0.2-FINAL.jar;C:\workspace\mavenRepository\commons-logging\commons-logging\1.1\commons-logging-1.1.jar;C:\workspace\mavenRepository\log4j\log4j\1.2.13\log4j-1.2.13.jar;C:\workspace\mavenRepository\cn\hutool\hutool-all\5.8.15\hutool-all-5.8.15.jar;C:\workspace\mavenRepository\cglib\cglib\3.2.5\cglib-3.2.5.jar;C:\workspace\mavenRepository\org\ow2\asm\asm\6.0_ALPHA\asm-6.0_ALPHA.jar;C:\workspace\mavenRepository\org\apache\ant\ant\1.9.6\ant-1.9.6.jar;C:\workspace\mavenRepository\org\apache\ant\ant-launcher\1.9.6\ant-launcher-1.9.6.jar;C:\workspace\mavenRepository\commons-io\commons-io\2.6\commons-io-2.6.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2020.1.2\lib\idea_rt.jar" com.zxw.xml.test.Test
Connected to the target VM, address: '127.0.0.1:53019', transport: 'socket'

2023-07-06 17:40:4510001kjhhj1232321
Disconnected from the target VM, address: '127.0.0.1:53019', transport: 'socket'

Process finished with exit code 0

格式化后的结果



    
        
            2023-07-06 17:40:45
            
            
            
            10001kjhhj1232321
            
            
            
                
                    
                    
                    
                    
                    
                    
                    
                
                
                    
                    
                    
                    
                    
                    
                    
                
            
        
    

你可能感兴趣的:(java,xml,前端)