注:
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);
}