注: 1.Bean类为继承自Map的封装类,可自由改动; 2.JsonUtils.toBean()为封装自org.json包,可自由更改
/** * 获取key.key集合 * @param json json字符串 * @param existLabel 存入key.key的集合 * @param curLabel 当前key是什么 */ public static void getJsonLabel(String json, Set<String> existLabel, String curLabel) { //判断是否是json格式 if (!checkIsJson(json)) return; Bean bean; //判断是否为null和”“ if (json == null || json.isEmpty()) { return; } //1.第一个字符为【,则代表为数组 //2.第一个字符为{,则代表为对象 if (json.substring(0, 1).equals("[")) { //第二个字符为{,则代表为对象数组 if (json.substring(1, 2).equals("{")) { bean = JsonUtils.toBeanList(json).get(0); } else { return; } } else if (json.substring(0, 1).equals("{")) { bean = JsonUtils.toBean(json); } else { return; } //对象中key的数量 int keyNum = bean.keySet().size(); if (keyNum > 0) { for (Object keyObj : bean.keySet()) { //前缀 String labelPrefix = ""; //判断当前key是否为空 if (curLabel.isEmpty()) { //为空的话前缀则为当前key labelPrefix = keyObj.toString(); } else { //不为空前缀则为key.当前key labelPrefix = curLabel + "." + keyObj.toString(); } //将前缀填入set集合 existLabel.add(labelPrefix); //获取值 Object obj = bean.get(keyObj); if (obj != null) { //1.是否为对象 //2.是否为数组 //3.在为字符串的情况下则进行json验证代码 if (obj instanceof Bean) { getJsonLabel(JsonUtils.toJson((Bean) bean.get(keyObj)), existLabel, labelPrefix); } else if (obj instanceof ArrayList) { getJsonLabel(JsonUtils.toJson((ArrayList) bean.get(keyObj)), existLabel, labelPrefix); } else if ((obj.toString().substring(0, 1).equals("{") || obj.toString().substring(0, 2).equals("[{")) && checkIsJson(obj.toString())) { getJsonLabel(obj.toString(), existLabel, labelPrefix); } } } } } /** * 判断规则 * 引号中的内容全部跳过,若想继续判断,可使用递归方式 * 为】时验证前方到【之间的,有多少,是否与{}对个数相差1 * :和:之间相差1个, * @return */ public static boolean checkIsJson(String json) { Deque deque = new LinkedList(); //需要添加到栈中的符号 String inDeque = "{[,:"; //判断是否为json验证的符号 String needSymbol = "{}[],:\""; //判断是否为引号 boolean isQuotationMarks = false; //判断数组是否为多个对象,对象即{} boolean isOpenArrayCount = false; //数组中对象的个数 int bracesAmount = 0; for (int i = 0; i < json.length(); i++) { //获取单个字符 String s = json.substring(i, i + 1); //判断单个字符是否为json验证所需的符号 if (needSymbol.indexOf(s) == -1) { continue; } //判断是否为引号 if (s.equals("\"")) { if (!isQuotationMarks) { isQuotationMarks = true; } else { isQuotationMarks = false; } } //引号之间的内容全部跳过 if (isQuotationMarks) { continue; } //将需要压入栈中的内容填入栈中 if (inDeque.indexOf(s) > -1) { //判断数组中是否为对象 if ("{".equals(s) && "[".equals(deque.peekFirst())) { isOpenArrayCount = true; } deque.addFirst(s); } //对象出栈 if (s.equals("}")) { //如果是数组对象,则开始计数 if (isOpenArrayCount) { bracesAmount++; } //冒号的数量 int commaAmount = 0; //都好的数量 int colonAmount = 0; //循环的次数为栈的大小 int cycleNum = deque.size(); for (int j = 0; j < cycleNum; j++) { //查看栈首是否为逗号 if (",".equals(deque.peekFirst())) { commaAmount++; } //查看栈首是否为冒号 if (":".equals(deque.peekFirst())) { colonAmount++; } //如果栈首是左括号就停止循环,并弹出 if ("{".equals(deque.removeFirst().toString())) { break; } } //1.逗号数量为0,即代表花括号中只有一个值 //2.逗号数量不为1,即代表逗号数量要比冒号数量少1 if (commaAmount != 0 && commaAmount + 1 != colonAmount) { return false; } } //数组出栈 if (s.equals("]")) { //对象之间逗号的数量 int commaAmount = 0; //判断是否为对象数组 boolean isObjArray = false; //循环的次数 int cycleNum = deque.size(); for (int j = 0; j < cycleNum; j++) { //判断栈首是否为右花括号,若是则代表为[{},{}]结构,若不是则代表为[,,]结构 if (j == 0 && "}".equals(deque.peekFirst())) { //是对象数组 isObjArray = true; //关闭对象判断,直至下次开启 isOpenArrayCount = false; } //栈首是否为逗号 if (",".equals(deque.peekFirst())) { commaAmount++; } //如果栈首是左中括号就停止循环,并弹出 if ("[".equals(deque.removeFirst().toString())) { break; } } //只有在是对象数组的情况下需要判断,逗号的数量比对象数量少1 if (isObjArray && bracesAmount != 0 && commaAmount + 1 != bracesAmount) { return false; } //对象数量清空 bracesAmount = 0; } } //若在json字符串循环完毕后栈中还存在数据,则代表json不是标准格式 if (deque.size() != 0) { return false; } return true; } public static void main(String[] args) { //String json = "{\"state\":{\"code\":10001,\"message\":\"{访:问a:问}\",\"timestamp\":1647398784788},\"body\":{}}"; /*String json = "{\n" + " \"definitions\": {\n" + " \"address\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"street_address\": \"{ 'type': 'string' }\",\n" + " \"city\": { \"type\": \"string\" },\n" + " \"state\": { \"type\": \"string\" }\n" + " },\n" + " \"required\": [\"street_address\", \"city\", \"state\"]\n" + " }\n" + " },\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"billing_address\": { \"$ref\": \"#/definitions/address\" },\n" + " \"shipping_address\": { \"$ref\": \"#/definitions/address\" }\n" + " }\n" + "}";*/ String json = "{ \"type\": \"string\" }"; JsonUtils.toBean(json); Set<String> existLabel = new HashSet<>(); getJsonLabel(json, existLabel, ""); System.out.println(existLabel); }