Json类型分析
场景: 基于用户配置的字符串,生成json装换的类型
package com.soul.base.test;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.ParameterizedTypeImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Type;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
public class TypeAnalysisTest {
public static void main(String[] args) throws Exception {
getTypes2("A");
System.out.println();
getTypes2("A<B>");
System.out.println();
getTypes2("A<B,C>");
System.out.println();
getTypes2("A<B,C,D>");
System.out.println();
getTypes2("A<B<B1,B2>,C>");
System.out.println();
getTypes2("A<B,C<C1,C2>>");
System.out.println();
getTypes2("A<B<B1,B2,B3>>");
System.out.println();
getTypes2("A<B,C<C1,C2,C3>>");
System.out.println();
getTypes2("A<B<B1,B2,B3>,C>");
System.out.println();
getTypes2("A<B,C<C1<C2<C3>>>,D<D1<D2<D3>>>>");
System.out.println();
getTypes2("A<B,C<C1,C2,C3>,D<D1<D2<D3>>>>");
System.out.println();
getTypes2("A<B<B1,B2,B3>,C<C1,C2,C3>,D<D1<D2<D3>>>>");
System.out.println();
getTypes2("A<B<B1,B2,B3>,C<C1<C2<C3>>>,D<D1<D2<D3>>>>");
System.out.println();
getTypes2("A<B<B1<B2<B3>>>,C<C1<C2<C3>>>,D<D1<D2<D3>>>>");
System.out.println();
getTypes2("A<B<B1<B2<B3>>>,C<C1<C2<C3>,C2<C3>>>,D<D1<D2<D3>>>>");
System.out.println();
getTypes2("A<B<B1<B2<B3>>>,C,D>");
System.out.println();
String responseStr = "{\"A\":{\"A1\":[\"A2\",\"A3\",\"A4\"]},\"B\":{\"B1\":null},\"C\":null}";
String types = "java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.util.List<java.lang.String>>>";
ParameterizedTypeImpl types3 = getTypes3(types);
Map<String,Map<String,List<String>>> map = JSONObject.parseObject(responseStr, types3);
System.out.println(map.get("A"));
System.out.println(map.get("A").get("A1").get(0));
System.out.println(map.get("B"));
System.out.println(map.get("C"));
}
public static LinkedList<String> init(String className) {
LinkedList<String> levelList = new LinkedList<>();
levelList.add(className);
return levelList;
}
public static void getTypes2(String types) {
//截取类型的开始下标
int startIndex = 0;
//截取类型的结束下标
int endIndex;
//上一次遇到的操作符号
char lastSymbol = '<';
Stack<List<String>> clazzStack = new Stack<>();
if (!types.contains("<")){
clazzStack.push(init(types));
}
types = types.replaceAll("\\s+", "");
for (int i = 0; i < types.length(); i++) {
endIndex = i;
char charAt = types.charAt(i);
// 注意: 每一次处理的是操作符号左边的数据
if (charAt == '<') {
// <开始符号, 压入元素
if (lastSymbol == '<'){
//<左侧为新层级且仅有一个元素,新建层并压入
clazzStack.push(init(types.substring(startIndex, endIndex)));
} else if (lastSymbol == ',') {
//<左侧为,的同层级,取历史层级压入
List<String> preLevelList = clazzStack.pop();
preLevelList.add(types.substring(startIndex, endIndex));
clazzStack.push(preLevelList);
} else if (lastSymbol == '>') {
//不存在 > < 中间没有,情况
//clazzStack.push(init(types.substring(startIndex, endIndex)));
System.out.println("unknown case > xxx <");
}
startIndex = endIndex + 1;
lastSymbol = '<';
} else if (charAt == ',') {
// ,同层级符号, 压入元素
if (lastSymbol == '<'){
//,左侧为新层级的第一个元素(,表示必定有多个元素),新建层并压入
clazzStack.push(init(types.substring(startIndex, endIndex)));
} else if (lastSymbol == ',') {
//,左侧为历史同层级的第N个元素,取历史层级压入
List<String> preLevelList = clazzStack.pop();
preLevelList.add(types.substring(startIndex, endIndex));
clazzStack.push(preLevelList);
} else if (lastSymbol == '>') {
// >, 必然连在一起, 直接跳过这个,开始下标修改即可
}
startIndex = endIndex + 1;
lastSymbol = ',';
} else if (charAt == '>') {
// > 结束符号, 进行业务逻辑处理
if (lastSymbol == '<'){
// <>表示当前层级仅一个元素
//业务处理, 当前层仅一个元素
String curLevelSingleName = '<' + types.substring(startIndex, endIndex) + '>';
List<String> preLevelList = clazzStack.pop();
//业务处理, 加入到父元素
String lastClassName = preLevelList.get(preLevelList.size() - 1) + curLevelSingleName;
preLevelList.remove(preLevelList.size() - 1);
preLevelList.add(lastClassName);
clazzStack.push(preLevelList);
} else if (lastSymbol == ',') {
// ,>表示当前层级有多个元素并结束,获取当前层最后一个元素后,拼接后加到前父元素
String preName = types.substring(startIndex, endIndex);
List<String> preLevelList = clazzStack.pop();
preLevelList.add(preName);
//业务处理, 整个层级拼接
String preNameList = '<' + StringUtils.join(preLevelList,",") + '>';
//业务处理, 再向上交给这层父节点处理
List<String> pre2LevelList = clazzStack.pop();
String lastClassName = pre2LevelList.get(pre2LevelList.size() - 1) + preNameList;
pre2LevelList.remove(pre2LevelList.size() - 1);
pre2LevelList.add(lastClassName);
clazzStack.push(pre2LevelList);
} else if (lastSymbol == '>') {
// >>表示当前层无元素,且上一层级结束(>>必然连接在一起, 不需要向前截取)
List<String> preLevelList = clazzStack.pop();
//业务处理, 整个层级拼接
String preNameList = '<' + StringUtils.join(preLevelList,",") + '>';
//业务处理, 再向上交给这层父节点处理
List<String> pre2LevelList = clazzStack.pop();
String lastClassName = pre2LevelList.get(pre2LevelList.size() - 1) + preNameList;
pre2LevelList.remove(pre2LevelList.size() - 1);
pre2LevelList.add(lastClassName);
clazzStack.push(pre2LevelList);
}
startIndex = endIndex + 1;
lastSymbol = '>';
}
}
System.out.println(clazzStack.pop().get(0));
System.out.println(types);
}
public static ParameterizedTypeImpl getTypes3(String types) throws Exception {
//截取类型的开始下标
int startIndex = 0;
//截取类型的结束下标
int endIndex;
//上一次遇到的操作符号
char lastSymbol = '<';
Stack<List<TypeNode>> clazzStack = new Stack<>();
if (!types.contains("<")){
clazzStack.push(initNode(types));
}
types = types.replaceAll("\\s+", "");
for (int i = 0; i < types.length(); i++) {
endIndex = i;
char charAt = types.charAt(i);
// 注意: 每一次处理的是操作符号左边的数据
if (charAt == '<') {
// <开始符号, 压入元素
if (lastSymbol == '<'){
//<左侧为新层级且仅有一个元素,新建层并压入
clazzStack.push(initNode(types.substring(startIndex, endIndex)));
} else if (lastSymbol == ',') {
//<左侧为,的同层级,取历史层级压入
List<TypeNode> preLevelList = clazzStack.pop();
preLevelList.add(new TypeNode(types.substring(startIndex, endIndex)));
clazzStack.push(preLevelList);
} else if (lastSymbol == '>') {
//不存在 > < 中间没有,情况
//clazzStack.push(init(types.substring(startIndex, endIndex)));
System.out.println("unknown case > xxx <");
}
startIndex = endIndex + 1;
lastSymbol = '<';
} else if (charAt == ',') {
// ,同层级符号, 压入元素
if (lastSymbol == '<'){
//,左侧为新层级的第一个元素(,表示必定有多个元素),新建层并压入
clazzStack.push(initNode(types.substring(startIndex, endIndex)));
} else if (lastSymbol == ',') {
//,左侧为历史同层级的第N个元素,取历史层级压入
List<TypeNode> preLevelList = clazzStack.pop();
preLevelList.add(new TypeNode(types.substring(startIndex, endIndex)));
clazzStack.push(preLevelList);
} else if (lastSymbol == '>') {
// >, 必然连在一起, 直接跳过这个,开始下标修改即可
}
startIndex = endIndex + 1;
lastSymbol = ',';
} else if (charAt == '>') {
// > 结束符号, 进行业务逻辑处理
if (lastSymbol == '<'){
// <>表示当前层级仅一个元素
List<TypeNode> curLevelList = initNode(types.substring(startIndex, endIndex));
//业务处理, 当前层与上1层拼接
dealCurAndPreNode(clazzStack, curLevelList);
}else if (lastSymbol == ',') {
// ,>表示当前层级有多个元素并结束,获取当前层最后一个元素后,拼接后加到前父元素
String preName = types.substring(startIndex, endIndex);
List<TypeNode> preLevelList = clazzStack.pop();
preLevelList.add(new TypeNode(preName));
//业务处理, 上1层与上2层拼接
dealCurAndPreNode(clazzStack, preLevelList);
}else if (lastSymbol == '>') {
// >>表示当前层无元素,且上一层级结束(>>必然连接在一起, 不需要向前截取)
List<TypeNode> preLevelList = clazzStack.pop();
//业务处理, 上1层与上2层拼接
dealCurAndPreNode(clazzStack, preLevelList);
}
startIndex = endIndex + 1;
lastSymbol = '>';
}
}
return clazzStack.pop().get(0).type;
}
public static void dealCurAndPreNode(Stack<List<TypeNode>> clazzStack, List<TypeNode> curLevelList) throws ClassNotFoundException {
//业务处理, 当前层仅一个元素
List<Type> clazzList = curLevelList.stream().map(node -> {
try {
if (null != node.type) {
return node.type;
}
return Class.forName(node.name);
} catch (ClassNotFoundException e) {
log.error("类找不到,配置异常,clazz:{}", node.name, e);
}
return null;
}).collect(Collectors.toList());
//业务处理, 加入到父元素
List<TypeNode> preLevelList = clazzStack.pop();
TypeNode pre2Node = preLevelList.get(preLevelList.size() - 1);
pre2Node.type = new ParameterizedTypeImpl(clazzList.toArray(new Type[]{}), null, Class.forName(pre2Node.name));
clazzStack.push(preLevelList);
}
static class TypeNode {
public String name;
public ParameterizedTypeImpl type;
public TypeNode() {
}
public TypeNode(String name) {
this.name = name;
}
@Override
public String toString() {
return "TypeNode{" +
"name='" + name + '\'' +
", type=" + type +
'}';
}
}
public static LinkedList<TypeNode> initNode(String className) {
LinkedList<TypeNode> levelList = new LinkedList<>();
levelList.add(new TypeNode(className));
return levelList;
}
}