Swagger json数据转为Controller,Entity java文件

需要的包


 <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

        <dependency>
            <groupId>io.github.biezhi</groupId>
            <artifactId>TinyPinyin</artifactId>
            <version>2.0.3.RELEASE</version>
        </dependency>
             <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
         <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.20</version>
        </dependency>
          <dependency>
      <groupId>org.freemarker</groupId>
      <artifactId>freemarker</artifactId>
      <version>2.3.31</version>
      <scope>compile</scope>
    </dependency>
package com.xiaoyun.shopadmin.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: XiaoYun461
 * @Date: 2022/2/19 16:57
 */
public class Swagger2Ftl {

    public static final String THIS_PACK = "com.xiaoyun.shopadmin";

    public static final String javaPath = System.getProperty("user.dir") + File.separator + "src" + File.separator + "main" + File.separator + "java";
    /**
     * 前缀分包
     */
    public static final String[] preNames = {"Sms", "Admin", "Sys", "Ums", "Cms", "Ims", "Mall", "Pms"};

    public static final String[] attrNames = {"integer", "string", "boolean", "object"};
    /**
     * 过滤请求
     */
    public static final String[] reqMethod_str = {"options", "head"};
    /**
     * sw.json 所在路径 默认 resources目录下
     */
    public static final File classPathResource = new ClassPathResource("sw.json").getFile();
    /**
     * entity.ftl 模板所在路径 默认 resources目录下
     */
    public static final File entityFile = new ClassPathResource("entity.ftl").getFile();
    /**
     * controller.ftl 模板所在路径 默认 resources目录下
     */
    public static final File controllerFile = new ClassPathResource("controller.ftl").getFile();


    public static void main(String[] args) {
        //格式化json对象
        JSONObject json = JSONUtil.readJSONObject(classPathResource, Charset.defaultCharset());
        //json 转为实体
        SwRoot swRoot = JSONUtil.toBean(json, SwRoot.class);
        //获取 root -> definitions
        Map<String, SwPojo> definitions = swRoot.getDefinitions();
        List<Entity> entityList = new ArrayList<>(definitions.size());
        //收集所有实体Entity方法
        definitions.forEach((key, value) -> {
            toEntity(entityList, value);
        });
        for (Entity entity : entityList) {
            String outJavaFile = jointClassPath(entity.getPackageName(), entity.getClassName());
            //执行生成 entity.java
            process(entity, entityFile, outJavaFile);
        }
        //收集所有Controller方法
        List<Controller> controllerList = getControllerList(swRoot);
        for (Controller controller : controllerList) {
            String outJavaFile = jointClassPath(controller.getPackageName(), controller.getClassName());
            //执行生成 controller.java
            process(controller, controllerFile, outJavaFile);
        }

    }

    private static List<Controller> getControllerList(SwRoot swRoot) {
        List<Controller> controllerList = new ArrayList<>();
        List<Tag> tags = swRoot.getTags();
        //初始化controller 并且填写备注
        initController(controllerList, tags);
        //建立Map对象,方便查找
        Map<String, Controller> controllerMap = controllerList.stream().collect(Collectors.toMap(Controller::getClassName, item -> item));
        Map<String, Map<String, Property>> paths = swRoot.getPaths();
        paths.forEach((path, map) -> {
            map.forEach((reqMethod, property) -> {
                if (checkReqMethod(reqMethod)) {
                    return;
                }
                Methods methods = new Methods();
                methods.setMethodUrl(path);
                String[] tempTags = property.getTags();
                Controller controller = controllerMap.get((checkControllerClassName(tempTags[0])));
                if (tempTags.length == 2) {
                    methods.setTag(tempTags[1]);
                }
                Set<Field> fieldList = new HashSet<>();
                List<JSONObject> parameters = property.getParameters();
                for (JSONObject parameter : parameters) {
                    String in = (String) parameter.get("in");
                    //忽略 header
                    if ("header".equals(in)) {
                        continue;
                    }
                    Field field = new Field();
                    String type = getType(controller, parameter);
                    String name = (String) parameter.get("name");
                    String description = (String) parameter.get("description");
                    Object aDefault = parameter.get("default");
                    if (Objects.nonNull(aDefault)) {
                        field.setDefaultValue(String.valueOf(aDefault));
                    }
                    Boolean required = (Boolean) parameter.get("required");
                    if (required) {
                        field.setRequired(required);
                    }
                    field.setFieldName(name);
                    field.setFieldDesc(description);
                    field.setFieldAttr(firstName2Up(checkAttrName(type)));
                    fieldList.add(field);
                }
                JSONObject jsonObject = property.getResponses().get("200");
                Object schema = jsonObject.get("schema");
                if (schema != null) {
                    Object resBodyDesc = ((JSONObject) schema).get("$ref");
                    if (resBodyDesc == null) {
                        resBodyDesc = ((JSONObject) schema).get("type");
                    }
                    String desc = String.valueOf(resBodyDesc);
                    methods.setResBodyDesc(desc);
                    //设置import
                    String body = desc2ResBody(desc);
                    if (!checkDataType(body)) {
                        setControllerImport(controller, body);
                    }
                    methods.setResBody(checkAttrName(body));
                }
                methods.setReqBody(fieldList);
                methods.setReqMethod(firstName2Up(reqMethod));
                methods.setMethodDesc(property.getSummary());
                methods.setMethodName(property.getOperationId());
                Set<Methods> methodsList = controller.getMethodsList();
                if (methodsList == null) {
                    methodsList = new HashSet<>();
                }
                methodsList.add(methods);
                controller.setMethodsList(methodsList);
            });
        });
        return controllerList;
    }

    private static boolean checkReqMethod(String reqMethod) {
        for (String s : reqMethod_str) {
            if (s.equals(reqMethod)) {
                return true;
            }
        }
        return false;
    }

    private static String getType(Controller controller, JSONObject parameter) {
        String type = null;
        if ("body".equals(parameter.get("in"))) {
            JSONObject object = (JSONObject) parameter.get("schema");
            Object schemaType = object.get("type");
            String ref = null;
            if (Objects.nonNull(schemaType) && "array".equals(String.valueOf(schemaType))) {
                JSONObject tempJson = ((JSONObject) object.get("items"));
                Object $ref = tempJson.get("$ref");
                if (Objects.nonNull($ref)) {
                    ref = String.valueOf($ref);
                    type = ref2ClassName(ref);
                    setControllerImport(controller, type);
                } else {
                    type = type2List(String.valueOf(tempJson.get("type")));
                }
            } else {
                ref = (String) object.get("$ref");
                if (ref == null) {
                    type = String.valueOf(schemaType);
                } else {
                    type = ref2ClassName(ref);
                    if (Validator.hasChinese(type)) {
                        type = chinese2Pinyin(type);
                    }
                    //检查是否是基本数据类型 string object
                    if (!checkDataType(type)) {
                        setControllerImport(controller, firstName2Up(type));
                    }
                }
            }
        } else {
            type = (String) parameter.get("type");
            if ("array".equals(type)) {
                type = (String) ((JSONObject) parameter.get("items")).get("type");
                type = type2List(type);
            } else if ("ref".equals(type)) {
                type = "Integer";
            } else if ("file".equals(type)) {
                type = "MultipartFile";
            }
        }
        return type;
    }

    /**
     * 检查是否是基本数据类型 string object
     *
     * @param type
     * @return
     */
    private static boolean checkDataType(String type) {
        type = type.toLowerCase();
        for (String attrName : attrNames) {
            if (attrName.equals(type)) {
                return true;
            }
        }
        return false;
    }

    private static void setControllerImport(Controller controller, String type) {
        //设置import
        Set<String> importClassName = controller.getImportClassName();
        if (importClassName == null) {
            importClassName = new HashSet<>();
        }
        importClassName.add(preNameAndEndNameGroup(type) + "." + type);
        controller.setImportClassName(importClassName);
    }

    private static void setEntityImport(Entity entity, String type) {
        //设置import
        Set<String> importClassName = entity.getImportClassName();
        if (importClassName == null) {
            importClassName = new HashSet<>();
        }
        importClassName.add(preNameAndEndNameGroup(type) + "." + type);
        entity.setImportClassName(importClassName);
    }

    private static void initController(List<Controller> controllerList, List<Tag> tags) {
        tags.stream().forEach(key -> {
            String name = key.getName();
            if (name.toLowerCase().endsWith("controller")) {
                Controller controller = new Controller();
                controller.setClassName(checkControllerClassName(name));
                controller.setPackageName(preNameAndEndNameGroup(name));
                controller.setDesc(key.getDescription());
                controllerList.add(controller);
            }
        });
    }

    private static String desc2ResBody(String desc) {
        if (desc.contains("/")) {
            String[] split = desc.split("/");
            desc = split[split.length - 1];
        }
        if (desc.contains("«")) {
            desc = desc.substring(0, desc.indexOf("«"));
        }
        return desc;

    }

    private static String checkControllerClassName(String name) {
        name = chinese2Pinyin(name);
        if (!name.contains("-")) {
            return name;
        }
        String[] split = name.split("-");
        StringBuilder sb = new StringBuilder();
        for (String s : split) {
            sb.append(firstName2Up(s));
        }
        return sb.toString();
    }


    /**
     * 拼凑 输出java所在的目录
     *
     * @param packageName
     * @param className
     * @return
     */
    private static String jointClassPath(String packageName, String className) {
        StringBuilder sb = new StringBuilder(javaPath);
        String[] split = packageName.split("\\.");
        for (int i = 0; i < split.length; i++) {
            sb.append(File.separator).append(split[i]);
        }
        return sb.append(File.separator).append(className).append(".java").toString();
    }

    /**
     * @param obj     数据集
     * @param ftlFile 模板文件所在的路径
     * @param outFile 生成的文件
     * @throws IOException
     * @throws TemplateException
     */
    public static void process(Object obj, File ftlFile, String outFile) {
        File file = new File(outFile);
        File outParentFile = file.getParentFile();
        if (!outParentFile.exists()) {
            outParentFile.mkdirs();
        }
        Configuration configuration = new Configuration(Configuration.getVersion());
        try (Writer out = new FileWriter(file)) {
            configuration.setDirectoryForTemplateLoading(ftlFile.getParentFile());
            configuration.setDefaultEncoding("utf-8");
            Template template = configuration.getTemplate(ftlFile.getName());
            template.process(obj, out);
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param entityList 收集对象的容器
     * @param swPojo     json格式化的实体对象 root-> definitions -> Map<String,SwPojo>
     */
    private static void toEntity(List<Entity> entityList, SwPojo swPojo) {
        Map<String, SwProperties> properties = swPojo.getProperties();

        // 有2种情况为空
        // 1. swPojo.type() 为 Object , swPojo.title() 为 Map
        // 2. swPojo.type() 为 Object , swPojo.title() 为 Map«string,object»
        if (properties == null) {
            return;
        }
        String title = swPojo.getTitle();
        String className = firstName2Up(title);
        // 含有 « 的 都是嵌套对象,不做处理 例如 CommonResult«CommonPage«UmsAdminNode»»
        // 后续 单个对象中 包含嵌套对象里的 类
        if (className.contains("«")) {
            return;
        }
        Entity entity = new Entity();
        // 检查是否有中文,将Class类名 中文转为拼音 , & 转为And
        className = chinese2Pinyin(className);
        entity.setDesc(title);

        List<Field> fieldList = new ArrayList<>();

        properties.forEach((key, value) -> {
            Field field = new Field();
            String type = value.getType();
            // 查看当前 type是否为空; type为空说明是一个引用对象, 一般在 $ref中查找
            if (type == null) {
                String $ref = value.get$ref();
                // $ref 一般为 #/definitions/ThreeRecommendRecordDB 这种格式,所以要 去掉 / ,取后面的类
                String name = ref2ClassName($ref);
                String attrName = firstName2Up(name);
                field.setFieldAttr(attrName);
                field.setFieldName(firstName2Down(key));
                setEntityImport(entity, name);
                // 查看是否为数组,一般都是 List 类型
            } else if ("array".equals(type)) {
                Map<String, String> items = value.getItems();
                if (CollUtil.isNotEmpty(items)) {
                    String tempType = items.get("type");
                    //判断 tempType, 不为空 说明是基本数据类型; 为空说明是 引用类型 或者是 Map
                    if (null != tempType) {
                        field.setFieldAttr(type2List(tempType));
                        field.setFieldName(firstName2Down(key));
                    } else {
                        String attrName = firstName2Up(ref2ClassName(items.get("$ref")));
                        // 判断 attrName 是否是Map 开头, 有2种情况
                        // 1. Map
                        // 2. Map«string,object»
                        if (attrName.startsWith("Map")) {
                            if (attrName.contains("«")) {
                                // Map«string,object» -> Map<String,Object>
                                int index = attrName.indexOf("«");
                                String[] split = attrName.substring(index + 1, attrName.length() - 1).split(",");
                                attrName = attrName.substring(0, index) + "<" + firstName2Up(split[0]) + "," + firstName2Up(split[1]) + ">";
                            } else {
                                attrName = "Map<String,String>";
                            }
                        } else {
                            setEntityImport(entity, attrName);
                        }
                        field.setFieldName(firstName2Down(key));
                        field.setFieldAttr("List<" + attrName + ">");
                    }
                }
                //基本数据类型直接处理
            } else {
                field.setFieldAttr(checkAttrName(type));
                field.setFieldName(firstName2Down(key));
            }
            //设置备注
            field.setFieldDesc(value.getDescription());
            fieldList.add(field);
        });
        entity.setFields(fieldList);
        entity.setClassName(className);
        entity.setPackageName(preNameAndEndNameGroup(className));
        entityList.add(entity);
    }

    private static String type2List(String tempType) {
        return "List<" + checkAttrName(tempType) + ">";
    }

    private static String chinese2Pinyin(String className) {
        if (Validator.hasChinese(className)) {
            String[] split = PinyinUtil.getPinyin(className, ",").split(",");
            StringBuilder sb = new StringBuilder();
            for (String str : split) {
                sb.append(firstName2Up(str));
            }
            if (className.contains("&")) {
                className = sb.toString().replace("&", "And");
            } else {
                className = sb.toString();
            }
        }
        return className;
    }

    /**
     * 属性开头大写 integer->Integer, number->BigDecimal
     *
     * @param attr integer ,string
     * @return
     */
    private static String checkAttrName(String attr) {
        for (String attrName : attrNames) {
            if (attrName.equals(attr)) {
                return firstName2Up(attrName);
            }
        }
        if ("number".equals(attr)) {
            return "BigDecimal";
        }
        return attr;


    }

    /**
     * 根据类名 分包
     *
     * @param name
     * @return
     */
    private static String preNameAndEndNameGroup(String name) {
        StringBuilder sb = new StringBuilder(THIS_PACK);
        for (int i = 0; i < preNames.length; i++) {
            String preName = preNames[i];
            if (name.startsWith(preNames[i])) {
                sb.append(".").append(firstName2Down(preName));
            }
        }
        if (name.toLowerCase().endsWith("controller")) {
            sb.append(".").append("controller");
        } else {
            sb.append(".").append("pojo");
        }
        if (name.endsWith("BO")) {
            sb.append(".").append("bo");
        } else if (name.endsWith("PO")) {
            sb.append(".").append("po");
        }
        return sb.toString();

    }

    /**
     * 首字母大写
     *
     * @param name
     * @return
     */
    private static String firstName2Up(String name) {
        return StrUtil.upperFirst(name);
    }

    /**
     * 首字母小写
     *
     * @param name
     * @return
     */
    private static String firstName2Down(String name) {
        return StrUtil.lowerFirst(name);
    }

    /**
     * 例如 : #/definitions/ThreeRecommendRecordDB 转为 ThreeRecommendRecordDB
     *
     * @param $ref
     * @return
     */
    private static String ref2ClassName(String $ref) {
        if (!$ref.contains("/")) {
            return null;
        }
        String[] split = $ref.split("/");
        return split[split.length - 1];
    }

    @Data
    public static class Controller {
        private String packageName;
        private String className;
        private Set<String> importClassName;
        private Set<Methods> methodsList;
        private String desc;

    }

    @Data
    @EqualsAndHashCode(of = {"methodUrl", "reqMethod"})
    public static class Methods {
        private String methodName;
        private String methodUrl;
        private String methodDesc;
        private String reqMethod;
        private Set<Field> reqBody;
        private String resBody;
        private String resBodyDesc;
        private String tag;


    }


    @Data
    public static class Entity {
        private String packageName;
        private String className;
        private Set<String> importClassName;
        private List<Field> fields;
        private String desc;
    }

    @Data
    @EqualsAndHashCode(of = {"fieldName"})
    public static class Field {
        private String fieldAttr;
        private String fieldName;
        private String fieldDesc;
        private Boolean required;
        private String defaultValue;
    }

    @Data
    public class SwRoot {
        private String swagger;
        private String info;
        private String host;
        private String basePath;
        private List<Tag> tags;
        private Map<String, Map<String, Property>> paths;
        private Map<String, SwPojo> definitions;
    }

    @Data
    public class Property {
        private String[] tags;
        private String summary;
        private String operationId;
        private String[] produces;
        private List<JSONObject> parameters;
        private Map<String, JSONObject> responses;
        private String deprecated;
    }


    @Data
    public class Tag {
        private String name;
        private String description;
    }

    @Data
    public class SwPojo {
        private String type;
        private Map<String, SwProperties> properties;
        private String title;
    }

    @Data
    public class SwProperties {
        private String type;
        private String format;
        private String description;
        private String $ref;
        private Map<String, String> items;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getFormat() {
            return format;
        }

        public void setFormat(String format) {
            this.format = format;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public String get$ref() {
            return $ref;
        }

        public void set$ref(String $ref) {
            this.$ref = $ref;
        }


        public Map<String, String> getItems() {
            return items;
        }

        public void setItems(Map<String, String> items) {
            this.items = items;
        }
    }

}

entity.ftl

package ${packageName};

<#if importClassName??>
<#list importClassName as name>
import ${name};
</#list>
</#if>
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import lombok.Data;
import io.swagger.annotations.ApiModelProperty;
<#if desc??>
/**
* ${desc}
*/
</#if>
@Data
public class ${className}  implements Serializable {

    <#list fields as fieldBean>

        <#if fieldBean.fieldDesc??>
        /**
        *  ${fieldBean.fieldDesc}
        */
        @ApiModelProperty(value = "${fieldBean.fieldDesc}")
        </#if>
        private <#if fieldBean.fieldAttr??>${fieldBean.fieldAttr}<#else>String</#if> ${fieldBean.fieldName};

    </#list>
}

controller.ftl

package ${packageName};
<#if importClassName??>
    <#list importClassName as item>
import ${item};
    </#list>
</#if>
import org.springframework.web.multipart.MultipartFile;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.time.LocalDateTime;
import java.math.BigDecimal;


@RestController
<#if  desc??>
@Api(tags = "${className}", description = "${desc}")
</#if>
public class ${className} {

<#list methodsList as item>
    <#if item.tag??>
     /**
     *  ${item.tag}
     */
    </#if>
    @${item.reqMethod}Mapping(value = "${item.methodUrl}")
    @ApiOperation("${item.methodDesc}")
    <#if item.reqBody?? && (item.reqBody?size > 0)>
    @ApiImplicitParams({
    <#list item.reqBody as req>
        <#if req.fieldName??>@ApiImplicitParam(name = "${req.fieldName}"<#if req.fieldDesc??>, value = "${req.fieldDesc}"</#if><#if req.defaultValue??>, defaultValue = "${req.defaultValue}"</#if><#if req.required??>, required = true</#if> )<#if req_has_next>,
        </#if></#if></#list>})</#if>
    public <#if item.resBody??>${item.resBody}<#else>String</#if> ${item.methodName}(<#if item.reqBody??><#list item.reqBody as req><#if req.fieldAttr??>${req.fieldAttr} ${req.fieldName} <#if req_has_next>,</#if></#if></#list></#if>) {
        //<#if  item.resBodyDesc??> ${item.resBodyDesc} </#if>
    <#if item.resBody??>    return new ${item.resBody}();<#else>return "OK";</#if>
    }
</#list>

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值