【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程序 ...
随机推荐
- shell脚本:Syntax error: Bad for loop variable错误解决方法(转)
Linux Mint中写了一个简单的shell脚本,利用for..do..done结构计算1+2+3......+100的值,结果执行"sh -n xxx.sh"检测语法时总是报错 ...
- WebLogic反序列化漏洞(CVE-2019-2725补丁绕过)
影响产品: Oracle WebLogic Server10.3.6.0.0 Oracle WebLogic Server12.1.3.0.0 影响组件: wls9_async_response.wa ...
- python高级特性-迭代器
凡是可作用于for循环的对象都是Iterable类型: 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列: 集合数据类型如list.dict.str等是Itera ...
- DevExpress GridControl 使用瀑布加载方式加载数据
从事winform开发已经快三年了,这三年中两年使用DevExpress控件进行winform系统开发,对Dev控件有自己的一些思考,下面就常用的表格控件GridControl的分页进行一些讨论. 在 ...
- markdown锚点
转:https://blog.csdn.net/u012260238/article/details/87815170 markdown 语法文档:https://www.w3cschool.cn/l ...
- 《BUG创造队》作业9:【Beta】冲刺 Scrum meeting 3
项目 内容 这个作业属于哪个课程 2016级软件工程 这个作业的要求在哪里 实验十三 团队作业9:Beta冲刺与团队项目验收 团队名称 BUG创造队 作业学习目标 (1)掌握软件黑盒测试技术:(2)学 ...
- Alpha冲刺随笔六:第六天
课程名称:软件工程1916|W(福州大学) 作业要求:项目Alpha冲刺(十天冲刺) 团队名称:葫芦娃队 作业目标:在十天冲刺里对每天的任务进行总结. 随笔汇总:https://www.cnblogs ...
- javascript单一复制粘贴
<div id="copy-txt">内容内容</div> <button type="submit" onclick=" ...
- Mac 下Wireshark 找不到网卡
终端上面,执行如下命令: sudo chgrp admin /dev/bpf* sudo chmod g+rw /dev/bpf*
- js清空数组
js-清空array数组 两种实现方式: 1.splice:删除元素并添加新元素,直接对数组进行修改,返回含有被删除元素的数组. arrayObject.splice(index,howmany,el ...