• 【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+",
    ");
            }
            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

  • 相关阅读:
    void及void指针含义的深刻解析
    jbpm入门样例
    给字符数组赋值的方法
    linux tar.gz zip 解压缩 压缩命令
    android 文件上传
    职员有薪水了
    sublime配置全攻略
    [置顶] WPF数据修改demo
    Java实现快速排序
    Java实现快速排序
  • 原文地址:https://www.cnblogs.com/heyang78/p/11923945.html
Copyright © 2020-2023  润新知