在swagger上⽣成关于json数据类型返回结果的描述
在swagger上⽣成关于json数据类型返回结果的描述
实现原理:在MyOperationBuilderPlugin类中读取controller类⽅法上的ApiReturnJsonArray注解和ApiReturnJsonObject注解,动态构建对应数据结构的类。
1. ApiReturnJsonArray表⽰的是list数据结构(⽤于接⼝返回值类型声明)
2. ApiReturnJsonObject表⽰map数据结构(⽤于接⼝返回值类型声明)
3. ApiJsonProperty表⽰key-value数据结构
4. ApiJsonObject表⽰map数据结构(⽤于接⼝⼊参声明)
注:⽬前代码只实现了List<Map<String,Object>>和Map<String,Object>两种结构,如果json数据结构存在三四层及以上,则需另外定义新的注解。总的来说,差不多是⼀层json数据结构就要定义⼀个注解,因为注解不允许继承和⾃引⽤。具体实现⽅式参照ApiReturnJsonArray、ApiReturnJsonObject、ApiJsonProperty的关系。
注解ApiReturnJsonObject表⽰返回结果的map结构
package com.hua.demo.swagger.dto;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 返回结果描述注解
* @author hua
* */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiReturnJsonObject {
ApiJsonProperty[]value();//对象属性值
String name()default"ReturnMap";//类名
}
注解ApiReturnJsonArray表⽰返回结果的数组结构
package com.hua.demo.swagger.dto;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 返回结果描述注解-数组
* @author hua
* */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiReturnJsonArray {
ApiReturnJsonObject[]values();
String name()default"ReturnList";//类名
}
注解ApiJsonProperty表⽰map中⼀个key-value的数据
package com.hua.demo.swagger.dto;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 接⼝⽂档⼊参字段说明
* @author hua
* */
@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiJsonProperty {
/
**
* 参数名称
* */
String name();
/**
* 参数的中⽂含义
* */
String value()default"";
/**
* 参数⽰例
* */
String example()default"";
/**
* ⽀持各种基础数据类型、或包装的数据类型
* */
String dataType()default"string";
/**
* 参数描述(想要在参数旁有中⽂解析,要给此属性赋值)
* */
String description()default"";
/**
object to
* 是否必填
* */
boolean required()default false;
//⽀持string 和 int
Class type()default String.class;
}
注解ApiJsonObject表⽰接⼝⼊参的map结构
package com.hua.demo.swagger.dto;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/
**
* 接⼝⽂档⼊参对象说明
* @author hua
* */
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME)
public @interface ApiJsonObject {
ApiJsonProperty[] value(); //对象属性值
String name() default "ParamMap";  //对象名
}
MyBaseBuildPlugin类⽤于动态构造⼀个类代表注解ApiReturnJsonArray和ApiReturnJsonObject的数据结果注:类名不能重复,不然会报frozon class的错
package com.hua.demo.swagger.plugin;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.TypeResolver;
import com.hua.demo.swagger.dto.ApiJsonProperty;
import javassist.*;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.*;
import llections.MapUtils;
import org.apachemons.lang.ObjectUtils;
import org.apachemons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import springfox.documentation.ts.DocumentationContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author hua
* */
@Component
public class MyBaseBuildPlugin {
@Autowired(required =false)
protected TypeResolver typeResolver;
/**
* 参数的全局索引,⽤于动态⽣成类,确保类名不会重复
* */
public static int paramIndex =0;
private ClassPool pool = Default();
/**
* ⽤于标记json结构中描述数据结构的key值
* */
private String childKey ="child";
/**
* 动态⽣成的Class名
* */
protected final static String basePackage ="com.hua.demo.swagger.dto.";
protected final String StringTypeName ="java.lang.String";
protected final String IntegerTypeName ="java.lang.Integer";
protected final String LongTypeName ="java.lang.Long";
protected final String FloatTypeName ="java.lang.Float";
protected final String DoubleTypeName ="java.lang.Double";
protected final String BooleanTypeName ="java.lang.Boolean";
protected final String ShortTypeName ="java.lang.Short";
/**
* 根据propertys中的值动态⽣成含有Swagger注解的javaBeen
* @param context
* @param propertys
* @param name 类名
*/
protected Class createRefModel(DocumentationContext context, ApiJsonProperty[] propertys, String name){
protected Class createRefModel(DocumentationContext context, ApiJsonProperty[] propertys, String name){
CtClass ctClass = pool.makeClass(basePackage + name);
try{
Class clazz = Class();
ResolvedType resolvedType = solve(clazz);
return clazz;
}catch(Exception e){
e.printStackTrace();
return null;
}
}
/***
* 此⽅法是实现了把当前⽅法上的所有ApiJsonProperty注解进⾏特定解析,解析成对应结构的json
* 1、⾸先根据是否含有'.'来进⾏分组
* 2、把含有'.'的部分重新进⾏解析,并把解析后的结果放到不含'.'的结果之中
* 3、把解析完成的数据进⾏
* @param context
* @param ctClass
* @param propertys
* */
protected void translatePropertyToJSONObject(DocumentationContext context,CtClass ctClass,ApiJsonProperty[] propertys)throws NotFoundException , CannotCompileException{
List<ApiJsonProperty> propertyList =new ArrayList<ApiJsonProperty>();
JSONObject propertyMap =new JSONObject();
for(ApiJsonProperty property : propertys){
if(property.name().contains(".")){
propertyList.add(property);
}else{
JSONObject propertyObj =ansferAnnationToJSONObject(property);
propertyMap.put(property.name(),propertyObj);
}
}
for(ApiJsonProperty property : propertyList){
JSONObject propertyObj =ansferAnnationToJSONObject(property);
String name = property.name();
String[] names = name.split("\\.");
propertyObj.put("name",names[1]);
if(property.name().contains("[")&& property.name().contains("]")){
String paramName = names[0].substring(0,names[0].indexOf("["));
int index = Integer.valueOf(names[0].substring(names[0].indexOf("[") + 1,names[0].indexOf("]")));
int index =0;
ainsKey(paramName)){
if(!JSONObject(paramName).containsKey(this.childKey)){
}
JSONArray array = JSONObject(paramName).getJSONArray(this.childKey);
if(array.size()<= index || (index)== null){
array.add(index,new JSONObject());
}
}
}else{
ainsKey(names[0])){
if(!JSONObject(names[0]).containsKey(this.childKey)){
}
}
}
}
this.buildPropertyClass(context,ctClass,propertyMap);
}
/**
*对JSONObject的数据进⾏类的动态⽣成,基本⼀层数据结构就要相应构造⼀个类
* @param context
* @param ctClass
* @param propertyMap
* */
protected void buildPropertyClass(DocumentationContext context,CtClass ctClass,JSONObject propertyMap)throws NotFoundException, CannotCompil eException{
for(Object key : propertyMap.keySet()){
JSONObject object = String(key));
Object child = (this.childKey);
Map<String, Object> params = JSONObject.JSONString(),
new TypeReference<Map<String, Object>>(){});
if(child == null || child instanceof String){
CtField ctField =ateField(params,ctClass);
ctClass.addField(ctField);
}else if(child instanceof JSONObject || child instanceof JSONArray){
String propertyClassName = Name()+"."+ key;
CtClass propertyClass = pool.makeClass(propertyClassName);
if(child instanceof JSONArray){
String datatype ="[L"+ Name()+";";
object.put("dataType",datatype);
params.put("dataType",datatype);
JSONObject innerObject = JSONArray(this.childKey).getJSONObject(0);
this.buildPropertyClass(context,propertyClass,innerObject);
}else{
object.put("dataType",Name());
params.put("dataType",Name());
JSONObject innerObject = JSONObject(this.childKey);
this.buildPropertyClass(context,propertyClass,innerObject);
}
ResolvedType resolvedType = Class());
CtField ctField =ateField(params,ctClass);
ctClass.addField(ctField);
}
}
}
/**
* 根据property的值⽣成含有swagger apiModelProperty注解的属性
* @param property
* @param ctClass 字段所在的类
*/
@SuppressWarnings("all")
private CtField createField(ApiJsonProperty property, CtClass ctClass)throws NotFoundException, CannotCompileException {
String dataType =PackDataTypeByName(property.dataType());
boolean required = quired();
//isSet == true,表⽰全部必选
if(this.isSet){
required =true;
}
CtClass fileType = (dataType);
CtField ctField =new CtField(fileType, property.name(), ctClass);
ctField.setModifiers(Modifier.PUBLIC);
ConstPool constPool = ClassFile().getConstPool();
AnnotationsAttribute attr =new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
Annotation ann =new Annotation("io.swagger.annotations.ApiModelProperty", constPool);
//下⾯添加MemberValue的值对应注解ApiModelProperty的属性
String value = property.value();
/
/value为空时,展⽰description中的内容
if(StringUtils.isBlank(value)){
value = property.description();
}
ann.addMemberValue("value",new StringMemberValue(value, constPool));

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。