下载地址:https://files.cnblogs.com/files/xiandedanteng/jsonformat20191126-2.zip
注意:本文仅为draft1版本,还有待完善。
先看整形效果(同级别按字典序排列,层次缩进,化单行为多行):
原句:
{"depts":[{"emps":[{"age":23,"id":1,"male":true,"name":"Andy","phone":"13000000001"},{"age":31,"id":2,"male":false,"name":"Bill","phone":"14000000001"},{"age":37,"id":3,"male":true,"name":"Cindy","phone":"15000000001"},{"age":41,"id":4,"male":false,"name":"Douglas","phone":"16000000001"},{"age":43,"id":5,"male":true,"name":"Eliot","phone":"17000000001"}],"id":"001","name":"Sales"},{"emps":[{"age":47,"id":6,"male":true,"name":"Felix","phone":"18000000001"},{"age":53,"id":7,"male":false,"name":"Gates","phone":"19000000001"},{"age":59,"id":8,"male":true,"name":"Hilton","phone":"2000000001"}],"id":"002","name":"Develop"}],"id":"01","name":"doogle"}
整形后的的文本:
{ "depts":[ { "emps":[ { "age":23, "id":1, "male":true, "name":"Andy", "phone":"13000000001", }, { "age":31, "id":2, "male":false, "name":"Bill", "phone":"14000000001", }, { "age":37, "id":3, "male":true, "name":"Cindy", "phone":"15000000001", }, { "age":41, "id":4, "male":false, "name":"Douglas", "phone":"16000000001", }, { "age":43, "id":5, "male":true, "name":"Eliot", "phone":"17000000001", }, ], "id":"001", "name":"Sales", }, { "emps":[ { "age":47, "id":6, "male":true, "name":"Felix", "phone":"18000000001", }, { "age":53, "id":7, "male":false, "name":"Gates", "phone":"19000000001", }, { "age":59, "id":8, "male":true, "name":"Hilton", "phone":"2000000001", }, ], "id":"002", "name":"Develop", }, ], "id":"01", "name":"doogle", }
这个效果是下面这个类做出来的,主要利用了栈,哈希表和正则表达式:
package com.hy; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.Stack; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sf.json.JSONObject; class StrDepth{ String str; int depth; public StrDepth(String str,int depth) { this.str=str; this.depth=depth; } } /** * 嵌套Json排序整形类 * @author 逆火 * * 2019年11月24日 下午3:37:40 */ public class NestedJsonSorter { // 每个栈替换对象的序列号 private int serialNumber=0; // 存放栈替换对象的哈希表 private Map<String,StrDepth> map; // 整形排序结束的最终结果 private String result; /** * 构造函数 * @param jsonStr */ public NestedJsonSorter(String jsonStr) { Stack<String> stk=new Stack<String>(); map=new LinkedHashMap<String,StrDepth>(); // 利用栈进行嵌套处理 String line=""; for(int i=0;i<jsonStr.length();i++){ char c=jsonStr.charAt(i); if(c=='['){ stk.push(line); line=""; }else if(c==']') { int depth=stk.size(); String sid=storeInMap(line,depth); line=stk.pop()+"["+sid+repeatedSpace(depth)+"]"; }else{ line+=c; } } // 最后留下ROOT SimpleJsonSorter sjs=new SimpleJsonSorter(line,0); String rawString=sjs.getFormattedJson(); // 用正则表达式对SN0001,SN0002还原成其代表的字符串 java.util.regex.Pattern pattern=Pattern.compile("SN\d{4}"); Matcher matcher=pattern.matcher(rawString); while(matcher.find()) { String key=matcher.group(0); rawString=rawString.replace(key, fetchValue(key)); matcher=pattern.matcher(rawString); } result=rawString; } // 得到整形排序结束的最终结果 public String getFormattedResult() { return result; } /** * 得到重复多次数的四个空格,放在行头当竖向定位用 * @param n * @return */ private static String repeatedSpace(int n) { return String.join("", Collections.nCopies(n, " ")); } /** * 从哈希表里取得SN000X代表的值 * @param key * @return */ private String fetchValue(String key) { StrDepth value=map.get(key); map.remove(key); return value.str; } /** * 把中括号内内容存入map * @param str * @param depth * @return */ private String storeInMap(String str,int depth) { serialNumber++; String key="SN"+String.format("%04d", serialNumber); StringBuilder sb=new StringBuilder(); String[] arr=str.split("(?<=[}])\s*,\s*(?=[{])"); // 注意要增加逗号两边的空白字符 2019-11-26 for(String objStr:arr) { SimpleJsonSorter sjs=new SimpleJsonSorter(objStr,depth); String retval=sjs.getFormattedJson(); sb.append(retval+", "); } String objsStr=sb.toString(); StrDepth value=new StrDepth(objsStr,depth); map.put(key, value); return key; } public static void main(String[] args) { Dept salesDept=new Dept(); salesDept.setId("001"); salesDept.setName("Sales"); salesDept.addEmp(new Emp(1,23,"Andy",true,"13000000001")); salesDept.addEmp(new Emp(2,31,"Bill",false,"14000000001")); salesDept.addEmp(new Emp(3,37,"Cindy",true,"15000000001")); salesDept.addEmp(new Emp(4,41,"Douglas",false,"16000000001")); salesDept.addEmp(new Emp(5,43,"Eliot",true,"17000000001")); Dept devDept=new Dept(); devDept.setId("002"); devDept.setName("Develop"); devDept.addEmp(new Emp(6,47,"Felix",true,"18000000001")); devDept.addEmp(new Emp(7,53,"Gates",false,"19000000001")); devDept.addEmp(new Emp(8,59,"Hilton",true,"2000000001")); Company company=new Company(); company.setId("01"); company.setName("doogle"); company.addDept(salesDept); company.addDept(devDept); JSONObject jobj = JSONObject.fromObject(company); System.out.println(jobj); NestedJsonSorter njs=new NestedJsonSorter(jobj.toString()); System.out.println(njs.getFormattedResult()); } }
对于非嵌套的Json,则用上一篇里提到的SimpleJsonSorter类就行了:
package com.hy; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sf.json.JSONObject; /** * 简单Json排序整形类 * @author 逆火 * * 2019年11月24日 上午11:57:39 */ public class SimpleJsonSorter { private int depth; private List<KeyValue> kvList; public SimpleJsonSorter(String jsonStr,int depth){ this.depth=depth; kvList=new ArrayList<KeyValue>(); java.util.regex.Pattern pattern=Pattern.compile("("([_a-zA-Z]+[_a-zA-Z0-9]*)")\s*[:]\s*([^,}]+)"); Matcher matcher=pattern.matcher(jsonStr); while(matcher.find()) { //System.out.println( matcher.group(1)+ ":"+matcher.group(3)); kvList.add(new KeyValue(matcher.group(1),matcher.group(3))); } } public String getFormattedJson() { Collections.sort(kvList); String prefix=getRepeatSpace(this.depth); StringBuilder sb=new StringBuilder(); sb.append(prefix+"{ "); for(KeyValue kv:kvList) { sb.append(prefix+kv.key+":"+kv.value+", "); } sb.append(prefix+"}"); return sb.toString(); } private String getRepeatSpace(int n) { return String.join("", Collections.nCopies(n, " ")); } protected final class KeyValue implements Comparable<KeyValue>{ private String key; private String value; public KeyValue(String key,String value) { this.key=key; this.value=value; } public int compareTo(KeyValue other) { return this.key.compareTo(other.key); } } public static void main(String[] args) { Emp felix=new Emp(6,47,"费力克死",false,"18000000001"); JSONObject deptJson = JSONObject.fromObject(felix); String jsonString=deptJson.toString(); System.out.println(jsonString); SimpleJsonSorter sjs=new SimpleJsonSorter(jsonString,2); System.out.println(sjs.getFormattedJson()); } }
至于Company,Dept,Emp等类,则是普通的Bean,没啥花头:
公司类:
package com.hy; import java.util.ArrayList; import java.util.List; public class Company { private String id; private String name; private List<Dept> depts; public Company addDept(Dept dept) { if(depts==null) { depts=new ArrayList<Dept>(); } depts.add(dept); return this; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Dept> getDepts() { return depts; } public void setDepts(List<Dept> depts) { this.depts = depts; } }
部门类:
package com.hy; import java.util.ArrayList; import java.util.List; public class Dept { private String id; private String name; private List<Emp> emps; public Dept addEmp(Emp emp) { if(emps==null) { emps=new ArrayList<Emp>(); } emps.add(emp); return this; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Emp> getEmps() { return emps; } public void setEmps(List<Emp> emps) { this.emps = emps; } }
雇员类:
package com.hy; public class Emp { private int id; private int age; private String name; private boolean isMale; private String phone; public Emp() { } public Emp(int id,int age,String name,boolean isMale,String phone) { this.id=id; this.age=age; this.name=name; this.isMale=isMale; this.phone=phone; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isMale() { return isMale; } public void setMale(boolean isMale) { this.isMale = isMale; } }
对于嵌套对象解析,并非一定要用编译方式,还是有别的路可以走的。
--END-- 2019年11月24日19:50:49