把swagger都整懵逼的返回对象

假设有个返回对象是这样的
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值