【json/regex】将嵌套对象生成的json文进行内部整形排序后再输出
下载地址: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+",\n"); } 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+"{\n"); for(KeyValue kv:kvList) { sb.append(prefix+kv.key+":"+kv.value+",\n"); } 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
【json/regex】将嵌套对象生成的json文进行内部整形排序后再输出的更多相关文章
- 【json/regex】将简单对象生成的json文进行内部排序后再输出
有这样一个实体类: package com.hy; public class Emp { private int id; private int age; private String name; p ...
- 做一次面向对象的体操:将JSON字符串转换为嵌套对象的一种方法
背景与问题 在 <一个略复杂的数据映射聚合例子及代码重构> 一文中,将一个JSON字符串转成了所需要的订单信息Map.尽管做了代码重构和配置化,过程式的代码仍然显得晦涩难懂,并且客户端使用 ...
- ObjC 利用反射和KVC实现嵌套对象序列化成JSON数据
原理: 0.创建一个新的可变字典:NSMutableDictionary 1.采用class_copyPropertyList函数遍历对象的属性 2.property_getName获取属性名,val ...
- C# json提取多层嵌套到数组-- C# json 数组
json比一般格式再复杂点的就像数组一样,有多层嵌套,研究了一下,记录代码如下: string jsonText = "{'name':'test','phone':'18888888888 ...
- java对象转化为json字符串并传到前台
package cc.util; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import ...
- Json对象与Json字符串的转化、JSON字符串与Java对象的转换
一.Json对象与Json字符串的转化 1.jQuery插件支持的转换方式: $.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符 ...
- 【Python】将对象存成json文件及从json取出对象
常用代码,单拎出来以备查. 对象存json文件: import json obj={'name':'张有财','age':39,'arr':[2,34,5,6,7,88,'李有钱']} with op ...
- Json对象与Json字符串的转化、JSON字符串与Java对象的转换(转)
一.Json对象与Json字符串的转化 1.jQuery插件支持的转换方式: $.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符 ...
- JSON字符串和Javascript对象字面量
JSON字符串和Javascript对象字面量 JSON是基于Javascript语法的一个子集而创建的,特别是对象和数组字面量语法. 正是由于JSON的这种特殊来历,导致很多Javascript程序 ...
随机推荐
- Python——迭代器&可迭代对象
可迭代对象 什么是对象: Python中,一切皆对象.一个变量,一个列表,一个字符串,文件句柄,函数等等都可称为一个对象.一个对象就是一个实例,就是实实在在的东西. 什么是迭代 迭代就是一个重复的过程 ...
- [ipsec][strongswan] strongswan源码分析-- (三) xfrm与strongswan内核接口分析
目录 strongwan sa分析(三) xfrm与strongswan内核接口分析 1. strongswan的实现 2. 交互机制 4. xfrm的消息通信的实现 strongwan sa分析(三 ...
- [LeetCode]1252. Cells with Odd Values in a Matrix
Given n and m which are the dimensions of a matrix initialized by zeros and given an array indices w ...
- ntohs的一个简单实现(将网络流中用两个字节16进制表示的资源数(如DNS)和长度转换为整形)
我们知道在由于大端机和小端机导致网络字节序和主机序有可能是有差异的,我们可以使用系统的ntohs,ntohl,htons和htonl这些处理函数进行转换,下面是我写的一个关于ntohs在处理小端机字节 ...
- flask的基础1
1.python 现阶段三大主流web框架Django Tornado Flask的对比 1.Django 主要特点是大而全,集成了很多组件,例如: Models Admin Form 等等, 不管你 ...
- springboot 之 使用poi进行数据的导出(一)
使用的是idea+restful风格 第一:引入依赖为: <!--poi--> <dependency> <groupId>org.apache.xmlbeans& ...
- 0025SpringMVC的几种响应方式
本文主要涉及到一下几种响应方式: 1.返回字符串2.返回void3.返回ModelAndView4.转发关键字forward和重定向关键字redirect返回字符串5.ajax调用返回json 具体实 ...
- C#:抽象类PK密封类
最近在看关于C#的书,看到了抽象类和抽象方法,另外还看到了密封类和密封方法,那么二者有什么联系又有什么区别,我把最近的收获分享给大家! 1.抽象类和抽象方法: ·C#使用abstract关键字,将类或 ...
- NET Framework 的泛型
NET Framework 的泛型 泛型是具有占位符(类型参数)的类.结构.接口和方法,这些占位符是类.结构.接口和方法所存储或使用的一个或多个类型的占位符.泛型集合类可以将类型参数用作它所存储的对象 ...
- H5性能测试,首屏时间统计(Argus)
Argus 腾讯质量开发平台,官网链接:https://wetest.qq.com/product/argus 主要针对性:H5的游戏性能测试 主要介绍: 独家首屏时间统计: 告别人工掐秒 自动统计首 ...