通过映射关系 动态转义为统一格式的数据 (支持 JSON 和 XML )

 

 

 

 在很多的时候 我们都会 需要 将不同格式的数据  转换为 统一的数据格式  

 

比如  将Json 源数据 
{
"b": [ { "c": "reference", "a": "atliwen", "t": "Sayings of the Century", "p": 8.95 } ] }
转换为

<book> 

  <category>reference</category>  

  <author>atliwen</author>  

  <title>Sayings of the Century</title>  

  <price>8.95</price>  

  <remark>种类:reference | 作者:atliwen | 标题:Sayings of the Century |定 价:8.95</remark>  

  <type>1</type> 

  <default>默认数据</default>

</book>

 由于客户提供的数据源格式不确定 或 其他服务提供的数据格式是我们需要的, 那么通常的做法是  为每个客户或服务 提供的数据 都写一遍 数据的转换 方法

 

 存在的问题是:

 

    如果客户或服务很多 , 而且还在不停的增长 。 我们将会不挺的 写 数据转换的方法

 

 需求:

 

   一个统一的转换数据的方法, 只需要配置一下字段映射关系 就可以  接收不同结构的数据  自动转换为统一的数据结构。 不需要我们写任何代码。

 

 根据 这个需求,我通过  XML 的 Xpath   和   JSON     第三方的 jsonPath  写出了这个统一转换数据结构的方法 

package com.thoth.Conversion;

import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.internal.JsonContext;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

public class OrderToXmlOrder
{

    /**
     * 将下单数据  转换 成EDI 数据
     *
     * @param order 订单数据
     * @param User  用户配置数据
     * @return
     * @throws Exception
     */
    public static String outEdiOrder(String order, String User, Integer type) throws Exception {

        Long startLong = System.currentTimeMillis();

        Document ediUserDocument = DocumentHelper.parseText(User);// 用户配置数据
        Element ediUserRoot = ediUserDocument.getRootElement();

        Element Edi = DocumentHelper.createDocument().addElement(ediUserRoot.getName());//  数据
        //
        Out(order, Edi, ediUserRoot, type);
        System.out.println("时间:" + (System.currentTimeMillis() - startLong));
        return Edi.asXML();
    }

    /**
     * 根据 用户配置节点 自动从数据源 查找数据 生成 EDI 数据节点
     *
     * @param order         数据源
     * @param Edi           EDI 数据节点
     * @param requestorders 用户配置节点
     * @param type          1 是 Xml  2 是 json
     */
    public static void Out(String order, Element Edi, Element requestorders, Integer type) throws DocumentException {

        //   Xml 值    <![CDATA[444]]>
        List<Element> listElements = requestorders.elements();
        Document orderDocument = DocumentHelper.createDocument();
        DocumentContext de = new JsonContext();
        if (type == 1) {
            orderDocument = DocumentHelper.parseText(order);// 订单数据
        } else {
            de = JsonPath.parse(order);
        }
        for (Element e : listElements) {
            getEdiXml(Edi, type, orderDocument, de, e);
        }

    }

    /**
     * 获取 数据源转换成 Edi 的XML
     *
     * @param Edi           EDI Xml
     * @param type          type 1 是 Xml  2 是 json
     * @param orderDocument Xml 数据 源
     * @param de            JSON 数据源
     * @param e             映射数据
     */
    private static void getEdiXml(Element Edi, Integer type, Document orderDocument, DocumentContext de, Element e) {
        // 是否有下级节点

        if (e.nodeCount() != 1) return;

        String TestValuse = e.getTextTrim();
        if (TestValuse == null || TestValuse == "") return;
        //default_   默认值   如果映射表达式 前缀 为default_  那么  后面的 直接赋值
        if (TestValuse.contains("default_")) {
            Edi.addElement(e.getName()).addText(TestValuse.replace("default_", ""));
            return;
        }
        String text = "";
        String[] strings = TestValuse.split(":");
        if (strings.length > 1) {
            text = strings[0] + " : ";
            TestValuse = strings[1];
        }


        // 获取 字段值
        List<String> nodesString = getStrings(type, orderDocument, de, TestValuse);

        //  表达式 判断是否 有    //Udf23[text()=N]   Udf23 节点的值等于 N
        if ("type".equals(e.getName().trim())) {
            if (nodesString.size() == 0) {
                Edi.addElement(e.getName()).addText("0");
                return;
            }
            Edi.addElement(e.getName()).addText("1");
            return;
        }
        orElement(Edi, e, text, nodesString);
    }

    /**
     * EDI Xml  字段值  生成
     *
     * @param Edi         Edi Xml
     * @param e
     * @param text
     * @param nodesString
     */
    private static void orElement(Element Edi, Element e, String text, List<String> nodesString) {
        if (nodesString.size() > 1) {
            for (String et : nodesString)
                text = text + "," + et;
            text = text.substring(1, text.length());
        } else text = text + nodesString.get(0);

        Element element = Edi.element(e.getName());

        if (element != null) {
            if (StringUtils.isEmpty(element.getText())) {
                element.addText(text.trim());
            } else {
                element.addText(" | " + text.trim());
            }
        } else {
            Edi.addElement(e.getName()).addText(text.trim());
        }
    }

    /**
     * 赋值
     *
     * @param type
     * @param orderDocument
     * @param de
     * @param testValuse
     * @return
     */
    private static List<String> getStrings(Integer type, Document orderDocument, DocumentContext de, String testValuse) {
        List<String> nodesString = new ArrayList<>();
        if (type == 1) {
            List<Element> nodesList = orderDocument.selectNodes(testValuse);
            if (nodesList.size() > 0) {
                for (Element ea : nodesList)
                    nodesString.add(ea.getTextTrim());
            }
        } else {
            try {
                 List<Object> list= de.read(testValuse);
                 for (Object o:list)
                     nodesString.add(o.toString());
            } catch (Exception ea) {
                Object o=de.read(testValuse);
                nodesString.add(o.toString());
            }
        }
        return nodesString;
    }

}

 

 

  测试 JSON 

    /**
     *  通过 映射 将 json 结构转换为统一的 Xml 结构
     * @throws Exception
     */
    @Test
    public void jsonToXml() throws Exception {

        //{
        //    b: [
        //        {
        //            c: "reference",
        //                    a: "atliwen",
        //                t: "SayingsoftheCentury",
        //                p: 8.95
        //        }
        //    ]
        //}
        String json ="{\"b\":[{\"c\":\"reference\",\"a\":\"atliwen\",\"t\":\"SayingsoftheCentury\",\"p\":8.95}]}";

        //<book>
        //  <category>$.b..c</category>
        //  <author>$.b..a</author>
        //  <title>$.b..t</title>
        //  <price>$.b..p</price>
        //  <remark>种类:$.b..c</remark>
        //  <remark>作者:$.b..a</remark>
        //  <remark>标题:$.b..t</remark>
        //  <remark>定价:$.b..p</remark>
        //  <type><![CDATA[$.b.[?(@.p>100)]]]></type>
        //  <default>default_默认数据</default>
        //</book>
        String userMapper="<book><category>$.b..c</category><author>$.b..a</author><title>$.b..t</title><price>$.b..p</price><remark>种类:$.b..c</remark><remark>作者:$.b..a</remark><remark>标题:$.b..t</remark><remark>定价:$.b..p</remark><type><![CDATA[$.b.[?(@.p>100)]]]></type><default>default_默认数据</default> </book>";


        String out= OrderToXmlOrder.outEdiOrder(json,userMapper,2);
        System.out.println(out);
        //<book>
        //  <category>reference</category>
        //  <author>atliwen</author>
        //  <title>SayingsoftheCentury</title>
        //  <price>8.95</price>
        //  <remark>种类 : reference | 作者 : atliwen | 标题 : SayingsoftheCentury | 定价 : 8.95</remark>
        //  <type>0</type>
        //  <default>默认数据</default>
        //</book>
    }

测试XML 

   @Test
    public void XmlToOrderXml() throws Exception {

        //<b>
        //  <c>reference</c>
        //  <a>atliwen</a>
        //  <t>SayingsoftheCentury</t>
        //  <p>8.95</p>
        //</b>
        String xml= "<b><c>reference</c><a>atliwen</a><t>SayingsoftheCentury</t><p>8.95</p></b>";

        //<book>
        //  <category>//c</category>
        //  <author>//a</author>
        //  <title>//t</title>
        //  <price>//p</price>
        //  <remark>种类://c</remark>
        //  <remark>作者://a</remark>
        //  <remark>标题://t</remark>
        //  <remark>定价://p</remark>
        //  <type><![CDATA[//p[text()>100]]]></type>
        //  <default>default_默认数据</default>
        //</book>
        String userMapper="<book><category>//c</category><author>//a</author><title>//t</title><price>//p</price><remark>种类://c</remark><remark>作者://a</remark><remark>标题://t</remark><remark>定价://p</remark><type><![CDATA[//p[text()>100]]]></type><default>default_默认数据</default></book>";

        String out= OrderToXmlOrder.outEdiOrder(xml,userMapper,1);
        System.out.println(out);

        //<book>
        //  <category>reference</category>
        //  <author>atliwen</author>
        //  <title>SayingsoftheCentury</title>
        //  <price>8.95</price>
        //  <remark>种类 : reference | 作者 : atliwen | 标题 : SayingsoftheCentury | 定价 : 8.95</remark>
        //  <type>0</type>
        //  <default>默认数据</default>
        //</book>
    }

 

当前代码还未在正式环境使用,  可能会有 异常。 请注意! 

 

 

 

 

  

 

posted @ 2017-02-22 15:02  atliwen  阅读(1610)  评论(0编辑  收藏  举报