Bean转成xml格式

Bean转换成xml格式

今天在调用机构的微信支付相关接口的时候,机构根据微信的规定,相关接口的入参必须为xml格式,格式如:

<xml>
<sign><![CDATA[80AAC36774B1144A5D00AA297B9D3B8D]]></sign>
<openid><![CDATA[oe59gt2SRLNflFCYoy1zZjHNab4g]]></openid>
<opertype>0</opertype>
<cardno><![CDATA[1000057017]]></cardno>
</xml>

在经过一番百度之后,发现了两个方法

1、用XStream转换成xml格式

OrganBalanceModel weixinBalanceRequest = new OrganBalanceModel();
        weixinBalanceRequest.setSign("80AAC36774B1144A5D00AA297B9D3B8D");
        weixinBalanceRequest.setOpenid("oe59gt2SRLNflFCYoy1zZjHNab4g");
        weixinBalanceRequest.setOpertype("0");
        weixinBalanceRequest.setCardno("1000057017");

        XStream xStream = new XStream(new Xpp3Driver());
        xStream.useAttributeFor(OrganBalanceModel.class);
        String s = xStream.toXML(weixinBalanceRequest);

        System.out.println(s);

转换成的xml格式如下:

<com.bangdao.project.common.model.OrganBalanceModel>
  <sign>80AAC36774B1144A5D00AA297B9D3B8D</sign>
  <openid>oe59gt2SRLNflFCYoy1zZjHNab4g</openid>
  <opertype>0</opertype>
  <cardno>1000057017</cardno>
</com.bangdao.project.common.model.OrganBalanceModel>

2、用JAXB转换成xml格式

 public static void main(String[] args) throws JAXBException, IOException {
        OrganBalanceModel weixinBalanceRequest = new OrganBalanceModel();
        weixinBalanceRequest.setSign("80AAC36774B1144A5D00AA297B9D3B8D");
        weixinBalanceRequest.setOpenid("oe59gt2SRLNflFCYoy1zZjHNab4g");
        weixinBalanceRequest.setOpertype("0");
        weixinBalanceRequest.setCardno("1000057017");

        JAXBContext context = JAXBContext.newInstance(OrganBalanceModel.class);
        OutputFormat of = new OutputFormat();
        of.setCDataElements(
                new String[] { "^conditionValue"});

        of.setPreserveSpace(true);
        of.setIndenting(true);
        ByteArrayOutputStream op = new ByteArrayOutputStream();
        XMLSerializer serializer = new XMLSerializer(op, of);
        SAXResult result = new SAXResult(serializer.asContentHandler());

        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);

        marshaller.marshal(weixinBalanceRequest , result);
        System.out.println(op.toString());
    }

转换成的xml如下:

<organBalanceModel><cardno>1000057017</cardno><openid>oe59gt2SRLNflFCYoy1zZjHNab4g</openid><opertype>0</opertype><sign>80AAC36774B1144A5D00AA297B9D3B8D</sign></organBalanceModel>

这两种都可以转换成标准的xml格式,但是微信入参要求带CDATA的xml,就需要自定义转义的规则,但是JAXB比较麻烦,所以我选择了自定义XStream转义规则。

重写XStream的writeText方法,自定义转义规则,实现转换成带CDATA的xml:

private static XStream xstream = new XStream(new XppDriver() {
        @Override
        public HierarchicalStreamWriter createWriter(Writer out) {
            return new PrettyPrintWriter(out) {

                boolean cdata = true;

                @SuppressWarnings("unchecked")
                @Override
                public void startNode(String name, Class clazz) {
                    super.startNode(name, clazz);
                }

                @Override
                protected void writeText(QuickWriter writer, String text) {
                    if (cdata) {
                        writer.write("<![CDATA[");
                        writer.write(text);
                        writer.write("]]>");
                    } else {
                        writer.write(text);
                    }
                }
            };
        }
    });

实现的xml格式如下:

<com.bangdao.project.common.model.OrganBalanceModel>
  <sign><![CDATA[80AAC36774B1144A5D00AA297B9D3B8D]]></sign>
  <openid><![CDATA[oe59gt2SRLNflFCYoy1zZjHNab4g]]></openid>
  <opertype><![CDATA[0]]></opertype>
  <cardno><![CDATA[1000057017]]></cardno>
</com.bangdao.project.common.model.OrganBalanceModel>

但是!!!微信的要求是opertype参数不带CDATA,也就是入参只是有的要用自定义规则。这样的话,全局直接改自定义规则是不现实的。在听完新宝岛之后,百度出来一种方法,就是自定义注解,需要带CDATA的参数,就加自定义注解,而不需要的就不带自定义注解,这样的方法就方便了许多,可以实现多种需求。

实现:
一、创建自定义注解@XStreamCDATA自定义注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface XStreamCDATA {
}
二、创建XStreamFactory,改写XPPDriver
public class XstreamFactory {
    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[");
                            writer.write(text);
                            writer.write("]]>");
                        } else {
                            writer.write(text);
                        }
                    }
                };
            }
        });
        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;
    }
}
三、创建工具类
public class BeanXmlUtils {
    private static  final XStream xStream = XstreamFactory.getXStream();

    /**
     * 对象转xml
     * @param obj 对象
     * @return
     */
    public static String toXml(Object obj) {
        xStream.processAnnotations(obj.getClass());
        return xStream.toXML(obj);
    }

    /**
     * xml转对象
     * @param xml
     * @return
     */
    public static Map CDATA2Map(String xml) {
        Map retMap = new HashMap();
        try {
            StringReader read = new StringReader(xml);
            // 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
            InputSource source = new InputSource(read);
            // 创建一个新的SAXBuilder
            SAXBuilder sb = new SAXBuilder();
            // 通过输入源构造一个Document
            Document doc = (Document) sb.build(source);
            // 指向根节点
            Element root = doc.getRootElement();
            List<Element> es = root.getChildren();
            if (es != null && es.size() != 0) {
                for (Element element : es) {
                    retMap.put(element.getName(), element.getValue());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return retMap;
    }
}

四、创建对象类

@XStreamAlias("xml")
@ApiModel(description = "查询余额机构入参")
public class OrganBalanceModel {

    /**
     * md5摘要
     */
    @XStreamCDATA
    private String sign;

    /**
     * 微信的用户Id
     */
    @XStreamAlias("openid")
    @XStreamCDATA
    private String openid;

    /**
     * 操作类型
     */
    @XStreamAlias("opertype")
    private String opertype;

    /**
     * 卡号
     */
    @XStreamAlias("cardno")
    @XStreamCDATA
    private String cardno;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值