假设有个返回对象是这样的
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<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 {
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);
* 循环获取改对象的父类字段
* @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
Swagger模式验证器
该库针对Swagger 2规范的definitions部分中definitions模型验证JSON对象。
InputStream spec = getClass() . getResourceAsStream( " mySpec.yaml " );
SwaggerValidator validator = SwaggerValidator . forYamlSchema(spec);
ProcessingReport report = validator . validate( " { \" name \" : \" Bob \" } " , " /definitions/User " );
if (report . isSuccess()) {
doStuff();
该库在Maven Central上可用:
< dependency>
如果请求参数为某个对象,还需要在swagger里显示出注释
第一步:在对象的类上加注解@ApiModel,类的字段上加注解@ApiModelProperty(value = "id或者姓名等注释")
第二步:controller类里直接使用@RequestBody OrderModel orderModel,json接收(如果是想表单提交,则用@ModelAttribute OrderMode...
首先,需要考虑的是,swagger会不会很申请,能在没有任何json数据的情况下,读取到数据的key,从而生成文档。把想要被swagger识别到的类型直接使用ResultBean,T为pojo类型,即可被swagger扫描到类型,生成T类型的文档信息。这里只是要了一下boolean,自定义类型也是一样的操作,到此已经能处理很多问题了,但是还是不能处理json的文档。上面的代码当然只是简单的统一了返回类型,其中data字段不能显示更加细节的信息,于是需要使用泛型。成功生成了json的信息。..........
关于snmp的开发,netsnmp目前的最新版本是5.7.3。 为了支持python的开发,网上的文章看了不少,走了不少弯路,所以总结一下,和大家共享。第一部分: 安装snmp程序以及服务。在Ubuntu中安装snmp的支持,有两种方法,第一种是直接通过apt-get进行安装。第二种是从netsnmp官网下载源码net-snmp-5.7.3.tar.gz,进行编译安装。本人对于第二种方法,查阅了网...
spring boot 处理 swagger 嵌套数据展示在开发的过程中,我们会常常使用swagger做我们的在线文档.我们会在对象的属性上使用@ApiModelProperty 等api注解,但是遇到对象嵌套的时候,如何返回一个嵌套的json文档就需要我们做一些简单的处理如果只在对象某个属性上使用 @ApiModelProperty 并不会起作用1234567891011121314151617...
目前使用Swagger2形成接口文档时,当系统设计的接口返回的类型不是实体对象时,Swagger2无法在接口文档页面中显示返回结果字段说明,比如返回json、map等可以存储key-val形式的类型;均无法在接口文档页面上显示返回的字段备注说明,所以怎么才能像实体对象一样显示正常的model字段说明是我们这次需要解决的问题;
首先告诉Swagger2该接口需要返回的字段具体有哪些
定义两个...