【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程序 ...
随机推荐
- Linux系统下文件压缩与打包命令
Linux系统下文件压缩与打包命令 常用的压缩文件拓展名 * .Z * .zip * .gz * .bz2 * .xz * .tar * .tar.gz * .tar.bz2 * .tar.xz 压缩 ...
- 零基础如何学好Python 之int 数字整型类型 定义int()范围大小转换
本文主题是讲python数字类型python int整型使用方法及技巧.它是不可变数据类型中的一种,它的一些性质和字符串是一样的,注意是整型不是整形哦. Python int有多种数字类型:整型int ...
- python 之类、self
类是什么 可以视为种类或者类型的同义词.所有的对象都属于某一个类,称为类的实例. 例如:鸟就是"鸟类"的实例.这就是一个有很多子类的一般(抽象)类:看到的鸟可能属于子类" ...
- set/priority_queue的运算符重载
#include<bits/stdc++.h> using namespace std; struct cmp { bool operator ()(int a, int b) //重载小 ...
- springcloud实践(二)之api网关:zuul
zuul是什么? front door. API Gateway.Zuul is a JVM based router and server side load balancer by Netflix ...
- 从零开始开发一个Spring Boot Starter
一.Spring Boot Starter简介 Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境( 条件 ...
- YAML_05 定义一个变量创建用户,设置密码
ansible]# vim user2.yml --- - hosts: cache remote_user: root vars: user: wangwu tasks: ...
- sql server vs mysql
1.中文: my.ini [mysqld] character-set-server=utf8 character-set-client=utf8 data\testdb\db.opt default ...
- Cogs 1708. 斐波那契平方和(矩阵乘法)
斐波那契平方和 ★★☆ 输入文件:fibsqr.in 输出文件:fibsqr.out 简单对比 时间限制:0.5 s 内存限制:128 MB [题目描述] ,对 1000000007 取模.F0=0, ...
- 洛谷 P3367 并查集模板
#include<cstdio> using namespace std; int n,m,p; ]; int find(int x) { if(father[x]!=x) father[ ...