假设有个返回对象是这样的
List<Map<String, PageResult<Map<String, List>, PageResult<Map<Integer, PageResult<Set,Map<String, ? extends CreateBiV3Result>, BigDecimal>>, FileBean, Date>, Date>>>
那他的返回格式应该是什么样子呢,于是我就用swagger试了一下
代码试这样写的
@ApiOperation("测试swagger返回数据格式")
@GetMapping("testResult")
public List<Map<String, Test.PageResult<Map<String, List<CompareTable>>, Test.PageResult<Map<Integer, Test.PageResult<Set<Test.TestBigDecimal>,
Map<String, ? extends CreateBiV3Result>, BigDecimal>>, FileBean, Date>, Date>>> testResult() {
return null;
}
结果swagger给我展示的是这样的
这就怪了,按说没问题啊,应该可以获取返回对象数据格式的啊,这才有了我自己的思考,swagger究竟试怎么将返回的class处理成一个json的呢?查了一遍发现swagger试通过spring的fox做的,具体我也没在研究,就想着自己能不能写一个根据返回的class生成一个默认的json格式的工具类呢?经过查阅资料,总算是完成了,下面就是我的代码
import com.google.gson.Gson;
import javassist.Modifier;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.util.*;
/**
* 根据泛型,json格式
*/
public class ClassToDefJson {
private Object object;
private Map<TypeVariable<? extends Class<?>>, Type> variableTypeMap = new LinkedHashMap<>();
private List<TypeVariable<? extends Class<?>>> typeParameters = new ArrayList<>();
private List<Type> actualTypeArguments = new ArrayList<>();
private ClassToDefJson parentClassToDefJson;
public static String toJson(Type type, Gson gson) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
return new ClassToDefJson(type, null).getJson(gson);
}
public static Object toDefObject(Type type) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
return new ClassToDefJson(type, null).getObject();
}
/**
* 构建泛型解析对象
*
* @param type
* @param classToDefJson
* @throws InstantiationException
* @throws IllegalAccessException
*/
private ClassToDefJson(Type type, ClassToDefJson classToDefJson) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
if (type == null || Void.class == type || Void.TYPE == type) {
return;
}
parentClassToDefJson = classToDefJson;
if (type instanceof Class) {
object = createObj((Class<?>) type);
} else if (type instanceof ParameterizedType) {
initVariableTypeMap((ParameterizedType) type);
object = createObj((Class<?>) ((ParameterizedType) type).getRawType());
} else if (type instanceof WildcardType) {
Type[] upperBounds = ((WildcardType) type).getUpperBounds();
object = new ClassToDefJson(upperBounds[0], this).getObject();
} else if (type instanceof GenericArrayType) {
Type genericComponentType = ((GenericArrayType) type).getGenericComponentType();
object = new Object[]{new ClassToDefJson(genericComponentType, this).getObject()};
} else if (type instanceof TypeVariable) {
if (parentClassToDefJson == null) return;
Type type1 = parentClassToDefJson.variableTypeMap.get(type);
object = new ClassToDefJson(type1, this).getObject();
} else {
throw new RuntimeException("无效的类型");
}
}
/**
* 根据class初始化默认对象
*
* @param cls
* @return
* @throws IllegalAccessException
* @throws InstantiationException
*/
private Object createObj(Class<?> cls) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
if (cls == null) return new Object();
if (List.class.isAssignableFrom(cls)) {
return createList();
} else if (Map.class.isAssignableFrom(cls)) {
return createMap();
} else if (Set.class.isAssignableFrom(cls)) {
return createSet();
} else if (baseType.containsKey(cls)) {
return baseType.get(cls);
} else {
if (cls.isInterface()) {
return new Object();
}
Object o = newInstance(cls);
if (cls.getName().contains("CellData")) {
System.out.println(o.getClass());
}
return getObjectMap(cls, o);
}
}
private Object getObjectMap(Class<?> cls, Object o) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
if (baseType.containsKey(cls)) {
return baseType.get(cls);
}
// 该map与o拥有相同的数据格式
Map<String, Object> objectMap = new LinkedHashMap<>();
List<Field> fields = new ArrayList<>();
addAllDeclaredFields(fields, cls);
addField(o, objectMap, fields);
return objectMap;
}
/**
* 通过反射创建对象,处理非静态内部类的情况
*
* @param cls
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
private Object newInstance(Class<?> cls) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
if (cls.isMemberClass()) { // 判断是否是内部类
if (!Modifier.isStatic(cls.getModifiers())) { // 如果不是静态内部类,初始化方式不一样
Class<?> declaringClass = cls.getDeclaringClass();
Object declaringObj = newInstance(declaringClass);
Constructor<?> declaredConstructor = cls.getDeclaredConstructor(declaringClass);
Object newInstance = declaredConstructor.newInstance(declaringObj);
return newInstance;
}
}
return cls.newInstance();
}
/**
* 创建set对象
*
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
private Object createSet() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
HashSet<Object> objects = new HashSet<>();
if (actualTypeArguments.size() != 1) return objects;
objects.add(createCollection(actualTypeArguments.get(0)));
return objects;
}
/**
* 创建map对象
*
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
private Object createMap() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
HashMap objects = new HashMap<>();
if (actualTypeArguments.size() != 2) return objects;
Object key = createCollection(actualTypeArguments.get(0));
Object val = createCollection(actualTypeArguments.get(1));
objects.put(key, val);
return objects;
}
/**
* 创建list对象
*
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
private Object createList() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
ArrayList<Object> objects = new ArrayList<>();
if (actualTypeArguments.size() != 1) return objects;
objects.add(createCollection(actualTypeArguments.get(0)));
return objects;
}
/**
* 创建集合
*
* @param type
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
private Object createCollection(Type type) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
if (type instanceof TypeVariable && this.parentClassToDefJson != null) {
type = this.parentClassToDefJson.variableTypeMap.get(type);
}
return new ClassToDefJson(type, this).getObject();
}
/**
* 组装对象的字段
*
* @param bean
* @param objectMap
* @param fields
* @throws IllegalAccessException
* @throws InstantiationException
*/
private void addField(Object bean, Map<String, Object> objectMap, List<Field> fields) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
for (Field field : fields) {
String name = field.getName();
if (Modifier.isFinal(field.getModifiers())) {
continue;
}
field.setAccessible(true);
Type genericType = field.getGenericType();
Object val = field.get(bean);
if (val != null) { // 有默认值,直接赋默认值
if (val instanceof Collection || val instanceof Map) {
int size = val instanceof Collection ? ((Collection) val).size() : ((Map) val).size();
if (size == 0) {
initFieldVal(objectMap, name, genericType);
} else {
objectMap.put(name, val);
}
} else {
// System.out.println("name:" + name + ",object:" + bean.getClass());
Object objectFieldVal = getObjectMap(val.getClass(), val);
objectMap.put(name, objectFieldVal);
}
} else {// 没有默认值,创建对象
initFieldVal(objectMap, name, genericType);
}
}
}
private void initFieldVal(Map<String, Object> objectMap, String name, Type genericType) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
ClassToDefJson classToDefJson = new ClassToDefJson(genericType, this);
Object object = classToDefJson.getObject();
objectMap.put(name, object);
// field.set(bean, object);
}
/**
* 循环获取改对象的父类字段
*
* @param fields
* @param cls
*/
private void addAllDeclaredFields(List<Field> fields, Class<?> cls) {
if (Object.class == cls) return;
Field[] declaredFields = cls.getDeclaredFields();
fields.addAll(Arrays.asList(declaredFields));
addAllDeclaredFields(fields, cls.getSuperclass());
}
/**
* 初始化泛型对应的数据类型
*
* @param type
*/
private void initVariableTypeMap(ParameterizedType type) {
Class<?> cls = (Class<?>) type.getRawType();
typeParameters.addAll(Arrays.asList(cls.getTypeParameters()));
actualTypeArguments.addAll(Arrays.asList(type.getActualTypeArguments()));
if (typeParameters.size() != actualTypeArguments.size()) throw new RuntimeException("数据异常");
for (int i = 0; i < typeParameters.size(); i++) {
variableTypeMap.put(typeParameters.get(i), actualTypeArguments.get(i));
}
}
private Object getObject() {
return object;
}
public String getJson() {
return getJson(new Gson());
}
public String getJson(Gson gson) {
if (gson == null) return getJson();
return gson.toJson(object);
}
private static final Map<Class<?>, Object> baseType = new HashMap<>();
/**
* 内置一些基础类型的默认值
*/
static {
baseType.put(String.class, "string");
baseType.put(Integer.class, "int");
baseType.put(Double.class, "double");
baseType.put(Float.class, "float");
baseType.put(Character.class, "char");
baseType.put(Long.class, "long");
baseType.put(Byte.class, "byte");
baseType.put(BigDecimal.class, "bigDecimal");
baseType.put(Date.class, "date");
baseType.put(Boolean.class, "boolean");
baseType.put(Short.class, "short");
Map<Class<?>, Object> esMap = new HashMap<>();
baseType.forEach((aClass, o) -> {
try {
Class<?> cls = Class.forName("[L" + aClass.getName() + ";");
esMap.put(cls, new Object[]{o});
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
});
baseType.putAll(esMap);
baseType.put(Integer.TYPE, "int");
baseType.put(new int[1].getClass(), new Object[]{"int"});
baseType.put(Double.TYPE, "double");
baseType.put(new double[1].getClass(), new Object[]{"double"});
baseType.put(Float.TYPE, "float");
baseType.put(new float[1].getClass(), new Object[]{"float"});
baseType.put(Character.TYPE, "char");
baseType.put(new char[1].getClass(), new Object[]{"char"});
baseType.put(Long.TYPE, "long");
baseType.put(new long[1].getClass(), new Object[]{"long"});
baseType.put(Byte.TYPE, "byte");
baseType.put(new byte[1].getClass(), new Object[]{"byte"});
baseType.put(Boolean.TYPE, "boolean");
baseType.put(new boolean[1].getClass(), new Object[]{"boolean"});
baseType.put(Short.TYPE, "short");
baseType.put(new short[1].getClass(), new Object[]{"short"});
baseType.put(File.class, "file");
baseType.put(InputStream.class, "inputStream");
baseType.put(OutputStream.class, "outputStream");
}
}
测试一下结果怎么样,还是用那个老长的返回结果对象:
Class<?> cls = Test.class;
Method test = cls.getMethod("testResult");
ResolvableType resolvableType = ResolvableType.forMethodReturnType(test);
Object object = ClassToDefJson.toDefObject(resolvableType.getType());
String json = gson.toJson(object);
System.out.println(json);
下面是结果:
[
{
"string": {
"msg": "string",
"code": "string",
"t": [
{
"string": [
{
"schemaPattern1": "string",
"schemaPattern2": "string",
"dbName1": "string",
"dbName2": "string",
"tableName": "string",
"dbUserName1": "string",
"dbUserName2": "string",
"dbHost2": "string",
"isDba2": false,
"isDba1": false,
"password2": "string",
"password1": "string",
"dbHost1": "string"
}
]
}
],
"t3s": [
"date"
],
"t2": {
"msg": "string",
"code": "string",
"t": [
{
"int": {
"msg": "string",
"code": "string",
"t": [
[
{
"bigDecimal": "bigDecimal",
"baseField": "string"
}
]
],
"t3s": [
"bigDecimal"
],
"t2": {
"string": {
"pageData": {
"pageNum": 1,
"pageSize": 10,
"sumTotal": 0,
"resultData": [],
"colDes": []
},
"resultList": [],
"tableBean": {
"queryId": null,
"tableId": null,
"htmlHeader": null,
"searchList": [],
"tableHeader": []
}
}
}
}
}
],
"t3s": [
"date"
],
"t2": {
"fileName": "string",
"isFile": 0,
"parentPath": "string"
}
}
}
}
]
Disconnected from the target VM, address: '127.0.0.1:60107', transport: 'socket'
Process finished with exit code 0
不错不错,味道好极了。
其实这里主要涉及的就是java反射的东西,以及对于java.lang.reflect.Type及其几个子类的应用
java.lang.Class
java.lang.reflect.ParameterizedType
java.lang.reflect.WildcardType
java.lang.reflect.GenericArrayType
java.lang.reflect.TypeVariable