解析XML和JSON内容的一点技巧的实例代码分享

解析XML和JSON内容的一点技巧

概述

在没有统一标准的情况下,一个系统对接多个外部系统往往会遇到请求接口响应数据异构的情况,有可能返回的是xml,也有可能返回
json。除了返回类型不同,内容结构也不尽相同。以xml类型为例,
接口1返回内容

    16112638767472747178067    OK    200    ...

登录后复制

接口2返回内容

    16112638767472747178068    成功    1    ...

登录后复制

如果在我们系统中为每种格式的内容针对处理显然是不合理的,上面的内容中我们只是关心三种信息,分别是业务ID、状态值和描述信息,那么可不可以抽象这三种信息,
获得这些信息后再进行业务逻辑处理。

解析XML和JSON

根据业务抽象我们需要从XML或者JSON内容中获得三种信息,我们这里将会使用XPath和JSONPath的方式来解析。比如获得接口1的重要信息,
我们可以设定三个XPath表达式,

{    bid: "/root/bizKey",    code: "/root/returnCode",    description: "/root/returnMsg"}

登录后复制

bid,code和description对应我们系统自己定义的字段名。
解析JSON内容也是同理的,只不过定义的是JSONPath表达式。

分两步走处理数据内容

假设我们从原始的XML和JSON数据中获得了bid,code和description信息,
从接口1获得

{    bid: '16112638767472747178067',    code: '200',    description: 'OK'}

登录后复制

从接口2获得

{    bid: '16112638767472747178068',    code: '1',    description: '成功'}

登录后复制

假设我们从接口1文档获知状态值200表示请求成功,从接口2文档获知状态值1表示请求成功,虽然他们都表示请求成功,但是我们还是不能
把他们原原本本地保存到我们的业务相关表中(当然这些响应数据还是需要保存到另外的记录表中的,至少方便排查问题)。
假设我们的业务相关表是这样设计的

字段名 类型 描述

bidstring业务IDcodeint状态值,0=初始,1=请求中,2=成功,3=失败descriptionstring描述

因此,我们还必须定义规则把接口1返回的状态值200转换为我们系统的2,把接口2返回的状态值1转换为我们系统的2。
总结一下,两步走解析XML和JSON数据内容

根据XPath或者JSONPath表达式解析获得重要信息

根据规则转换状态值

第一步解析数据获得重要信息

以XML为例,

public class XmlParseUtils {    private DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();    private XPathFactory xpathFactory = XPathFactory.newInstance();        /**     *      * @param param    数据内容     * @param paths 表达式     * @return     * @throws Exception     */    public Map parse(String param, Map paths) throws Exception{        InputSource inputSource = new InputSource(new StringReader(param));        Document document = dbFactory.newDocumentBuilder().parse(inputSource);        Map map = Maps.newHashMap();        for(String key : paths.keySet()) {            XPath xpath = xpathFactory.newXPath();            Node node = (Node) xpath.evaluate(paths.get(key), document, XPathConstants.NODE);            if(node == null) {                throw new Exception("node not found, xpath is " + paths.get(key));            }            map.put(key, node.getTextContent());        }        return map;    }}

登录后复制

parse函数的返回类型也可以是Map,暂且用Map。

第二步根据规则转换状态值

这一步稍稍有点麻烦,不过我们先不考虑代码实现,反正你能想到的可能别人已经帮你实现了。首先我们根据接口文档定义规则,写出规则表达式(或者其他的什么),
又是表达式。假设接口1的返回的状态值比较简单,只有200表示成功,其他情况都是失败,那么我们可以这样定义规则,

code.equals("200") ? 2: 3

登录后复制

或者

23

登录后复制登录后复制

亦或者

function handle(arg) {    if(arg == 200) {        return 2;    }    return 3;}handle(${code})

登录后复制

以上根据同一份文档定义了三种不同类型的状态值转换规则,肯定需要三种不同的实现。下面一一说明,

三目表达式

code.equals(“200”) ? 2: 3是一个三目表达式,我们将使用jexl引擎来解析,利用第一步解析数据获得重要信息的结果,我们可以这样做

    public Object evaluateByJexl(String expression, Map context) {        JexlEngine jexl = new JexlBuilder().create();        JexlExpression e = jexl.createExpression(expression);        JexlContext jc = new MapContext(context);        return e.evaluate(jc);    }

登录后复制

FreeMarker模板

23

登录后复制登录后复制

处理这段模板我们可以这么做

    /**     *      * @param param FreeMarker模板     * @param context     * @return     * @throws Exception     */    public String render(String param, Map context) throws Exception {        Configuration cfg = new Configuration();        StringTemplateLoader stringLoader = new StringTemplateLoader();        stringLoader.putTemplate("myTemplate",param);        cfg.setTemplateLoader(stringLoader);        Template template = cfg.getTemplate("myTemplate","utf-8");        StringWriter writer = new StringWriter();        template.process(context, writer);        return writer.toString();    }

登录后复制

如果FreeMarker模板比较复杂,从模板预编译成Template可能会消耗更多的性能,就要考虑把Template缓存起来。

JavaScript代码段

function handle(arg) {    if(arg == 200) {        return 2;    }    return 3;}handle(${code})

登录后复制

这段js代码中存在${code},首先它需要使用FreeMarker渲染得到真正的handle方法的调用参数,然后

    public Object evaluate(String expression) throws Exception {        ScriptEngineManager manager = new ScriptEngineManager();        ScriptEngine engine = manager.getEngineByName("javascript");        return engine.eval(expression);    }

登录后复制

ScriptEngineManager的性能估计不太乐观,毕竟是一个语言的引擎。

不同转换规则实现的比较

类型 实现 优点 缺点

三目表达式Jexl简单(easy)简单(simple)FreeMarker模板FreeMarker—-JavaScript代码段FreeMarker + ScriptEngine直观过程复杂,性能问题

看起来Freemarker是一个不错的选择。
至此两步走小技巧已经实现了,都是利用了现成的代码实现。

或许我们会这样的挑战,在做状态值转换时需要知道当前系统某个业务状态值的情况,
此时Freemarker表达式可能是这样的,

223

登录后复制

这里我们可以使用Freemarker的特性,自定义Java函数或工具类,在模板中调用。

以上就是解析XML和JSON内容的一点技巧的实例代码分享的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2491595.html

(0)
上一篇 2025年3月5日 00:32:16
下一篇 2025年3月5日 00:33:53

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 详细介绍XML和JSON区别

    今个去面试,一个人事经理问我xml和json的区别我没答上来感觉很难过,于是就回来后就查阅相关资料写点东西:: 1.定义介绍(1).XML定义扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文…

    编程技术 2025年3月5日
    300

发表回复

登录后才能评论