zoukankan      html  css  js  c++  java
  • 通过映射关系 动态转义为统一格式的数据 (支持 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>
        }

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

      

  • 相关阅读:
    关于用网线连开发板和电脑网卡问题
    信号量同步编程
    信号量互斥编程
    信号通讯
    有名管道通讯
    dell 燃 7000 系列 7460/7560 禁用触控板 触摸板
    关于错误node_modules/@types/jasmine/index.d.ts(39,52): error TS1005: '=' expected.
    环境配置,nodejs,cnpm,git,webstorm,powershell,
    gitflow工作流
    <问题汇总>ionic2开发app
  • 原文地址:https://www.cnblogs.com/atliwen/p/6429027.html
Copyright © 2011-2022 走看看