手写一个json格式化 api
最近写的一个东西需要对json字符串进行格式化然后显示在网页上面。
我就想去网上找找有没有这样的api可以直接调用。百度 json api ,搜索结果都是那种只能在网页上进行校验的工具,没有api。
那只有自己去实现一个json 格式化工具。
仔细分析,实现起来并不是很困难,至少思路很清晰。
需要解决的几个问题:
- 对json的校验:主要是符号的匹配;
- 格式化预处理:去除键值对之间的空白字符;
- 格式化:主要是缩进的问题,要符合json通常展示的格式。
解决的办法:
- 针对A问题:
可以采用栈去匹配符号,大括号、中括号、双引号等。
- 针对B问题:
可以用fastjson的JSONObject.toString()方法实现,自动去除键值对之间的空白字符。
- 针对C问题:
在需要换行的地方追加\n,缩进的地方追加\t。通过控制追加的\t的个数从而控制缩进量。如:
"{"、"[" 后面追加 \n,并且\t在上次数量上加一;
"}"、"]" 追加\n,\t在上次的数量上减一;
",": 追加\n和上次相同数量的\t。
具体实现:
1 package com.lm.algorithm.json; 2 3 import com.alibaba.fastjson.JSONException; 4 import com.alibaba.fastjson.JSONObject; 5 6 /** 7 * Created by LiuMian on 2015/12/17. 8 * 将json字符串添加 换行符和制表符使其能够直接在网页上按照通常的json格式显示 9 */ 10 public class JSONFormat { 11 12 private String src; 13 private int TABLength = 0; 14 15 private final String BRACKET_LEFT = "["; 16 private final String BRACKET_RIGHT = "]"; 17 private final String BRACE_LEFT = "{"; 18 private final String BRACE_RIGHT = "}"; 19 private final String COMMA = ","; 20 private final String LINE_BREAK = "\n"; 21 private final String TAB = "\t"; 22 23 24 public JSONFormat(String src){ 25 this.src = src; 26 } 27 28 public String format() throws JSONException{ 29 try{ 30 JSONObject json = JSONObject.parseObject(src); 31 }catch (JSONException e){ 32 //对json进行简单的校验,如果不符合格式那么jsonobject在解析的时候会报错 33 throw e; 34 } 35 return format(src); 36 } 37 38 private String format(String src) { 39 StringBuffer result = new StringBuffer(); 40 char[] srcArray = src.toCharArray(); 41 for (int index = 0; index < src.length(); index++) { 42 result.append(srcArray[index]); 43 44 if (BRACE_LEFT.equals(String.valueOf(srcArray[index]))) //{ 45 result.append(appendLINE_BREAKAndTAB(++TABLength)); 46 47 if (BRACE_RIGHT.equals(String.valueOf(srcArray[index]))) //} 48 result.insert(result.length() - 1, appendLINE_BREAKAndTAB(--TABLength)); 49 50 if (BRACKET_LEFT.equals(String.valueOf(srcArray[index]))) //[ 51 result.append(appendLINE_BREAKAndTAB(++TABLength)); 52 53 if (BRACKET_RIGHT.equals(String.valueOf(srcArray[index]))) //] 54 result.insert(result.length() - 1, appendLINE_BREAKAndTAB(--TABLength)); 55 56 if (COMMA.equals(String.valueOf(srcArray[index]))) //, 57 result.append(appendLINE_BREAKAndTAB(TABLength)); 58 } 59 return result.toString(); 60 } 61 62 //追加换行符和 确定长度的制表符 63 private String appendLINE_BREAKAndTAB(int TABTimes) { 64 StringBuffer temp = new StringBuffer(); 65 temp.append(appendLINE_BREAK()); 66 temp.append(appendTAB(TABTimes)); 67 return temp.toString(); 68 } 69 70 private String appendLINE_BREAK() { 71 return LINE_BREAK; 72 } 73 74 private String appendTAB(int TABTimes) { 75 StringBuffer temp = new StringBuffer(); 76 for (int i = 0; i < TABTimes; i++) { 77 temp.append(TAB); 78 } 79 return temp.toString(); 80 } 81 82 public static void main(String[] args) { 83 String toFormat = "{\"status\": \"3\",\"message\": \"\",\"errCode\": \"0\",\"data\": [{\"time\": \"2013-02-26 16:47\",\"context\": \"客户 同事收发家人 已签收 派件员 张xx\"},{\"time\": \"2013-02-26 07:33\",\"context\": \"吉林省xx市xx公司 的派件员 张金达 派件中 派件员电话15xxx73xx87\"},{\"time\": \"2013-02-26 06:02\",\"context\": \"xx省xx市xx公司 已收入\"},{\"time\": \"2013-02-25 15:42\",\"context\": \"xx省xx转运中心公司已发出\"},{\"time\":\"2013-02-25 14:59\",\"context\":\"xx省xx转运中心公司已拆包\"},{\"time\": \"2013-02-24 18:11\",\"context\":\"辽宁省大连市中山区四部公司 已收件\"},{\"time\": \"2013-02-24 17:59\",\"context\":\"辽宁省大连市公司 已收入\"},{\"time\":\"2013-02-23 17:10\",\"context\":\"辽宁省大连市中山区xxxx公司 的收件员 王xx 已收件\" }],\"html\":\"\",\"mailNo\":\"71xxxxx624\",\"expTextName\":\"圆通快递\",\"expSpellName\":\"yuantong\",\"update\":\"1375155719\",\"cache\":\"33196560\",\"ord\":\"DESC\"}"; 84 JSONFormat jsonFormat = new JSONFormat(toFormat); 85 System.out.println(jsonFormat.format()); 86 } 87 88 }
效果图:
1 { 2 "status": "3", 3 "message": "", 4 "errCode": "0", 5 "data": [ 6 { 7 "time": "2013-02-26 16:47", 8 "context": "客户 同事收发家人 已签收 派件员 张xx" 9 }, 10 { 11 "time": "2013-02-26 07:33", 12 "context": "吉林省xx市xx公司 的派件员 张金达 派件中 派件员电话15xxx73xx87" 13 }, 14 { 15 "time": "2013-02-26 06:02", 16 "context": "xx省xx市xx公司 已收入" 17 }, 18 { 19 "time": "2013-02-25 15:42", 20 "context": "xx省xx转运中心公司已发出" 21 }, 22 { 23 "time":"2013-02-25 14:59", 24 "context":"xx省xx转运中心公司已拆包" 25 }, 26 { 27 "time": "2013-02-24 18:11", 28 "context":"辽宁省大连市中山区四部公司 已收件" 29 }, 30 { 31 "time": "2013-02-24 17:59", 32 "context":"辽宁省大连市公司 已收入" 33 }, 34 { 35 "time":"2013-02-23 17:10", 36 "context":"辽宁省大连市中山区xxxx公司 的收件员 王xx 已收件" 37 } 38 ], 39 "html":"", 40 "mailNo":"71xxxxx624", 41 "expTextName":"圆通快递", 42 "expSpellName":"yuantong", 43 "update":"1375155719", 44 "cache":"33196560", 45 "ord":"DESC" 46 }
如果把这个放在web项目里面,然后别人就可以根据api协议以Get或者Post请求的方式来调用你的json格式化工具啦~~
不足:没有对A问题进行实现,只是简单的借用了fastjson的JSONObject.parseObject()方法。
这样做虽然简单,但是有明显的缺陷:如果某一行不符合json格式要求你只能通过抛出一个异常的方式告知调用者,而不能准确的定位在某一行。
这个格式化工具最难的地方也是在这里,需要用栈来匹配符号,这就要求对json有比较清晰地了解。
大家有好的思路或者想法,欢迎一起交流~
欢迎转载!
除非经过作者本人同意,转载请注明出处并附上原文链接!