ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用Antlr将json翻译成XML(转)

2022-09-09 17:00:42  阅读:288  来源: 互联网

标签:XML String Antlr void ctx JSONParser json public


本文代码来自《Antlr权威指南》

现在我们传递数据一般都是要json,因为它短小精悍,占用空间小。

但是在数年之前,XML还被用作万金油。

如有你有一个客户,还停留在远古时代,他偏要你提供XML格式的数据接口,你该怎么办?

谁也不想写两套接口吧?这对于一些古老的大型项目简直是个灾难。

其实完全没必要,我们只需要写一个方法,将json转成XML即可。

首先我们需要json的语法文件JSON.g4,来自原书的资源文件。

// Derived from http://json.org

grammar JSON;
@header{package com.example.json;}
json:   object
    |   array
    ;

object
    :   '{' pair (',' pair)* '}' # AnObject
    |   '{' '}'                  # EmptyObject
    ;
pair:   STRING ':' value ;

array
    :   '[' value (',' value)* ']' # ArrayOfValues
    |   '[' ']'                    # EmptyArray
    ;

value
    :   STRING  # String
    |   NUMBER  # Atom
    |   object  # ObjectValue
    |   array   # ArrayValue
    |   'true'  # Atom
    |   'false' # Atom
    |   'null'  # Atom
    ;

STRING :  '"' (ESC | ~["\\])* '"' ;

fragment ESC :   '\\' (["\\/bfnrt] | UNICODE) ;
fragment UNICODE : 'u' HEX HEX HEX HEX ;
fragment HEX : [0-9a-fA-F] ;

NUMBER
    :   '-'? INT '.' [0-9]+ EXP? // 1.35, 1.35E-9, 0.3, -4.5
    |   '-'? INT EXP             // 1e10 -3e4
    |   '-'? INT                 // -3, 45
    ;
fragment INT :   '0' | [1-9] [0-9]* ; // no leading zeros
fragment EXP :   [Ee] [+\-]? INT ; // \- since - means "range" inside [...]

WS  :   [ \t\n\r]+ -> skip ;

剩下的工作就简单多了,根据语法文件生成词法分析和语法分析器。

下面就需要我们自己的代码了。

针对不同的json元素,我们需要进行不同的处理逻辑。

然后将他们组装起来,成为一个XML格式的数据

下面是一个原有的json数据

{
    "description" : "An imaginary server config file",
    "logs" : {"level":"verbose", "dir":"/var/log"},
    "host" : "antlr.org",
    "admin": ["parrt", "tombu"],
    "aliases": []
}

我们的代码

/***
 * 将json翻译成XML,非常经典和实用
 * 使用ParseTreeProperty暂存每个节点的内容,最后打印全部语法树
 ***/
public class JSON2XML {
    public static class XMLEmitter extends JSONBaseListener {
        ParseTreeProperty<String> xml = new ParseTreeProperty<String>();

        String getXML(ParseTree ctx) {
            return xml.get(ctx);
        }

        void setXML(ParseTree ctx, String s) {
            xml.put(ctx, s);
        }

        public void exitJson(JSONParser.JsonContext ctx) {
            setXML(ctx, getXML(ctx.getChild(0)));
        }

        public void exitAnObject(JSONParser.AnObjectContext ctx) {
            StringBuilder buf = new StringBuilder();
            buf.append("\n");
            for (JSONParser.PairContext pctx : ctx.pair()) {
                buf.append(getXML(pctx));
            }
            setXML(ctx, buf.toString());
        }

        public void exitEmptyObject(JSONParser.EmptyObjectContext ctx) {
            setXML(ctx, "");
        }

        public void exitArrayOfValues(JSONParser.ArrayOfValuesContext ctx) {
            StringBuilder buf = new StringBuilder();
            buf.append("\n");
            for (JSONParser.ValueContext vctx : ctx.value()) {
                buf.append("<element>"); // conjure up element for valid XML
                buf.append(getXML(vctx));
                buf.append("</element>");
                buf.append("\n");
            }
            setXML(ctx, buf.toString());
        }

        public void exitEmptyArray(JSONParser.EmptyArrayContext ctx) {
            setXML(ctx, "");
        }

        public void exitPair(JSONParser.PairContext ctx) {

            String tag = stripQuotes(ctx.STRING().getText());
            JSONParser.ValueContext vctx = ctx.value();
            String x = String.format("<%s>%s</%s>\n", tag, getXML(vctx), tag);
            setXML(ctx, x);
        }

        public void exitObjectValue(JSONParser.ObjectValueContext ctx) {
            // analogous to String value() {return object();}
            setXML(ctx, getXML(ctx.object()));
        }

        public void exitArrayValue(JSONParser.ArrayValueContext ctx) {
            setXML(ctx, getXML(ctx.array())); // String value() {return array();}
        }

        public void exitAtom(JSONParser.AtomContext ctx) {
            setXML(ctx, ctx.getText());
        }

        public void exitString(JSONParser.StringContext ctx) {
            setXML(ctx, stripQuotes(ctx.getText()));
        }

        //剥离json双引号
        public static String stripQuotes(String s) {
            if (s == null || s.charAt(0) != '"') return s;
            return s.substring(1, s.length() - 1);
        }
    }

    public static void main(String[] args) throws Exception {
        String fileName = "listener/json/t.json";
        URL url = Resources.getResource(fileName);
        String sdl = Resources.toString(url, Charsets.UTF_8);
        System.out.println(sdl);
        CodePointCharStream input = CharStreams.fromString(sdl);
        JSONLexer lexer = new JSONLexer(input);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        JSONParser parser = new JSONParser(tokens);
        parser.setBuildParseTree(true);
        ParseTree tree = parser.json();
        // show tree in text form
//        System.out.println(tree.toStringTree(parser));

        ParseTreeWalker walker = new ParseTreeWalker();
        XMLEmitter converter = new XMLEmitter();
        walker.walk(converter, tree);
        System.out.println(converter.getXML(tree));
    }
}

我们应用ParseTreeProperty来暂存了各个节点的内容。

然后这些节点最终会聚合成一个完整的XML数据。

下面展示输出的结果

<description>An imaginary server config file</description>
<logs>
<level>verbose</level>
<dir>/var/log</dir>
</logs>
<host>antlr.org</host>
<admin>
<element>parrt</element>
<element>tombu</element>
</admin>
<aliases></aliases>

一个完美的json2XML翻译器就完成了!

标签:XML,String,Antlr,void,ctx,JSONParser,json,public
来源: https://www.cnblogs.com/wangbin2188/p/16673399.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有