Java实现XML序列化

业务背景

本地环境需要对接第三方系统,通过HTTP协议发送XML报文,并解析相应结果。鉴于XML报文信息相对特殊,特创建该文章进行记录。

场景一

客户提供的XML报文样例如下:



    
    
        
            
                
                    51
                
                
                    C80001
                
            
            
                
                    CRMWD-20230731-3333N
                
                
                    2023-08-04
                
                
                    006007
                
                
                    2023-07-31
                
                
                    0301004
                
                
                    0301001
                
                
                    
                        CRMWD-20230731-3333N(买入),21交行CRMW012(21东方医药MTN001),¥84000.00
                    
                    
                        84000.00
                    
                    
                        五矿证券
                    
                    
                        海通证券中证登资金开户行
                    
                    
                        233455
                    
                    
                        G海通证券股份有限公司上海自贸试验区区分公司
                    
                    
                        0000
                    
                    
                        【G海通自贸】
                    
                    
                        海通证券中证登资金账户名
                    
                    
                        30100001
                    
                    
                        CRMWD-20230731-3333N
                    
                
                
                    
                        测试文件1.docx
                    
                    
                      UEsDBAoAAAAAAIdO4kAAAAAAAAAAAAAAAAAJAAAAZG9jUHJvcHMvUEsDBBQAAAAIAIdO4kBPl+bFqgEAAJgCAAAQAAAAZG9jUHJvcHMvYXBwLnhtbJ2Sz2vUQBTH74L/Q8g9mUw2WTdldsqa2pPgwqbusQyTt5tgMjPMTMvuTTxIvRS
                    
                    
                        649042
                    
                
				
                    
                        测试文件2.docx
                    
                    
                       UEsDBAoAAAAAAIdO4kAAAAAAAAAAAAAAAAAJAAAAZG9jUHJvcHMvUEsDBBQAAAAIAIdO4kBPl+bFqgEAAJgCAAAQAAAAZG9jUHJvcHMvYXBwLnhtbJ2Sz2vUQBTH74L/Q8g9mUw2WTdldsqa2pPgwqbusQyTt5tgMjPMTMvuTTxIvRS
                    
                    
                        649042
                    
                
            
        
    

上述文件实现逻辑部分,相对特殊的部分是messageRequestBody的fileList部分,一般标准化的输出中外面应该还有一层结构,为了实现上述效果,我们可以创建相应的Java对象模型如下:

@Data
@Accessors(chain = true)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(namespace = StringUtils.EMPTY, name = "messageRequestBody")
@JacksonXmlRootElement(namespace = StringUtils.EMPTY, localName = "messageRequestBody")
public class EsbCapitalPayParameterDTO implements Serializable {
    /**
    *  来源单据编号
    */
    private String from_order_code;

    /**
    *  申请日期
    */
    private String apply_date;

    /**
    *  申请部门
    */
    private String apply_org;

    /**
    *  申请人
    */
    private String apply_owner;

    /**
    *  资金使用部门
    */
    private String use_dept;

    /**
    *  币种
    */
    private String money_type;

    /**
    *  是否逐笔计量
    */
    private String is_count;

    /**
    *  资金是否预约
    */
    private String is_appointment;

    /**
    *  计划付款日期
    */
    private String plan_pay_date;

    /**
    *  审批类型
    */
    private String business_type;

    /**
    *  管理分类
    */
    private String use_business_line;
    /**
    *
    */
    @XmlElement(name = "capital")
    private EsbCapitalPayL2ParameterDTO capital;

    /**
    * 附件
    * 以数组方式传递
    * 数据库映射:
    */
    @XmlElement(name = "fileList")
    private List fileList;
}
@Data
@Accessors(chain = true)
public class EsbCapitalPayFileDTO implements Serializable {
    /**
    * 文件名
    */
    private String fileName;


    /**
    * 文件字符串
    * 文件转为Base64字符串
    */
    private String fileBase64;


    /**
    * 文件大小
    */
    private long fileSize;

    @XmlTransient
    @JsonIgnore
    private String attachmentNo;
}

现在如果要序列化成上述messageRequestBody节点中的内容,可以使用如下序列化方法:

public static  String serializeToXml(T parameter) {
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(parameter.getClass());
            Marshaller marshaller = jaxbContext.createMarshaller();
            // 禁用格式化输出, 这将导致生成的XML文档没有额外的空格、缩进和换行符。
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
            // 在序列化对象时去掉
            // 低版本的使用com.sun.xml.bind.xmlDeclaration,高版本用com.sun.xml.internal.bind.xmlDeclaration
            // marshaller.setProperty("com.sun.xml.bind.xmlDeclaration", false);
            marshaller.setProperty("com.sun.xml.internal.bind.xmlDeclaration", false);

            StringWriter stringWriter = new StringWriter();
            marshaller.marshal(parameter, stringWriter);

            return stringWriter.toString();
        }
        catch (Exception exception) {
            throw new BusinessException(exception.getMessage(), exception);
        }
    }

需要注意的是,我们在EsbCapitalPayParameterDTO 类中使用注解@XmlAccessorType(XmlAccessType.FIELD),这样序列化出来的结果中就只有一层,否则就会出现这种两层结构。

@XmlAccessorType(XmlAccessType.FIELD)是一个JAXB注解,用于指定JAXB在访问字段时使用的访问类型。它可以应用于类级别或包级别。

当应用于类级别时,它指示JAXB应该访问类中的所有字段,而不是访问getter和setter方法。这意味着您不需要为每个字段编写getter和setter方法,JAXB将直接访问字段进行序列化和反序列化。

当应用于包级别时,它指示JAXB应该访问该包中所有类的字段,而不是访问getter和setter方法。

在您提供的情况下,@XmlAccessorType(XmlAccessType.FIELD)应用于类级别,表示JAXB将访问EsbCapitalPayParameterDTO类中的所有字段进行序列化和反序列化。这意味着您不需要为每个字段编写getter和setter方法,JAXB将直接访问字段。

请注意,@XmlAccessorType(XmlAccessType.FIELD)注解只适用于字段访问,不适用于方法访问。如果您希望使用方法访问,请使用@XmlAccessorType(XmlAccessType.PROPERTY)注解。

你可能感兴趣的:(java,xml,开发语言)