使用Antlr将json翻译成XML(转)
作者:互联网
本文代码来自《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