Springfox生成的api-doc无法与swagger-codegen

时间:2019-01-14 06:17:30

标签: swagger swagger-codegen springfox swagger-editor

我正在测试是否可以使用springfox生成的api-doc通过swagger-codegen生成Java客户端代码。

我使用springfox-demos中的boot-swagger模块,生成的api-doc如下所示(格式漂亮)

{
  "swagger": "2.0",
  "info": {
    "description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
    "version": "2.0",
    "title": "Springfox petstore API",
    "termsOfService": "http://springfox.io",
    "contact": {
      "name": "springfox"
    },
    "license": {
      "name": "Apache License Version 2.0",
      "url": "https://github.com/springfox/springfox/blob/master/LICENSE"
    }
  },
  "host": "localhost:8080",
  "basePath": "/springfox",
  "tags": [
    {
      "name": "category-controller",
      "description": "Category Controller"
    }
  ],
  "paths": {
    "/categories{?categories}": {
      "post": {
        "tags": [
          "category-controller"
        ],
        "summary": "map",
        "operationId": "mapUsingPOST",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "name": "categories",
            "in": "query",
            "description": "categories",
            "required": false,
            "type": "array",
            "items": {
              "type": "string"
            },
            "collectionFormat": "multi"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "ONE",
                  "TWO",
                  "THREE"
                ]
              }
            }
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      }
    },
    "/category/Resource{?someEnum}": {
      "get": {
        "tags": [
          "category-controller"
        ],
        "summary": "search",
        "operationId": "searchUsingGET",
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "name": "someEnum",
            "in": "query",
            "description": "someEnum",
            "required": true,
            "type": "string",
            "enum": [
              "ONE",
              "TWO",
              "THREE"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "string"
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      }
    },
    "/category/map": {
      "get": {
        "tags": [
          "category-controller"
        ],
        "summary": "map",
        "operationId": "mapUsingGET",
        "produces": [
          "*/*"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/definitions/Pet"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      }
    },
    "/category/{id}": {
      "post": {
        "tags": [
          "category-controller"
        ],
        "summary": "someOperation",
        "operationId": "someOperationUsingPOST",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "id",
            "required": true,
            "type": "integer",
            "format": "int64"
          },
          {
            "in": "body",
            "name": "userId",
            "description": "userId",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      }
    },
    "/category/{id}/map{?test}": {
      "post": {
        "tags": [
          "category-controller"
        ],
        "summary": "map",
        "operationId": "mapUsingPOST_1",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "id",
            "required": true,
            "type": "string"
          },
          {
            "name": "test",
            "in": "query",
            "description": "test",
            "required": true,
            "items": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      }
    },
    "/category/{id}/{userId}": {
      "post": {
        "tags": [
          "category-controller"
        ],
        "summary": "ignoredParam",
        "operationId": "ignoredParamUsingPOST",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "*/*"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "id",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "201": {
            "description": "Created"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        }
      }
    }
  },
  "definitions": {
    "Category": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        }
      },
      "title": "Category"
    },
    "Map«string,Pet»": {
      "type": "object",
      "title": "Map«string,Pet»",
      "additionalProperties": {
        "$ref": "#/definitions/Pet"
      }
    },
    "Pet": {
      "type": "object",
      "properties": {
        "category": {
          "$ref": "#/definitions/Category"
        },
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "identifier": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        },
        "photoUrls": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "status": {
          "type": "string",
          "description": "pet status in the store",
          "allowEmptyValue": false,
          "enum": [
            "available",
            "pending",
            "sold"
          ]
        },
        "tags": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Tag"
          }
        }
      },
      "title": "Pet"
    },
    "Tag": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "name": {
          "type": "string"
        }
      },
      "title": "Tag"
    }
  }
}

代码生成失败,并且看起来api-doc.json甚至不适合使用swagger规范。

我将代码粘贴到swagger editor中,它抱怨很多错误,例如

Semantic error at paths./categories{?categories} 
Query strings in paths are not allowed.
Jump to line 18

那么可以从Springfox生成的api-doc.json生成客户端代码吗?

1 个答案:

答案 0 :(得分:0)

阅读Springfox Reference Documentation的文档后,我已经解决了这个问题!

以下格式是因为默认情况下springfox应用RFC 6570

./categories{?categories} 

3.2。配置说明

  

一个示例是两个API:首先,http://example.org/findCustomersBy?name=Test用于按名称查找客户。根据RFC 6570,这将表示为http://example.org/findCustomersBy {?name}。其次,http://example.org/findCustomersBy?zip=76051通过zip查找客户。根据RFC 6570,这将表示为http://example.org/findCustomersBy {?zip}。

我在问题中未提及的另一个问题:

    "Map«string,Pet»": { // The generated JSON contains special characters
      "type": "object",
      "title": "Map«string,Pet»",
      "additionalProperties": {
        "$ref": "#/definitions/Pet"
      }
    }

文档清楚地提到了swagger-codegen的情况:

6.8.3。更改通用类型的命名方式

  

默认情况下,具有泛型的类型将用'\ u00ab'(<<),'\ u00bb'(>>)和逗号标记。像swagger-codegen之类的东西可能会出现问题。您可以通过实现自己的GenericTypeNamingStrategy来覆盖此行为。例如,如果希望将List编码为“ ListOfString”,将Map编码为“ MapOfStringAndObject”,则可以在插件自定义期间将forCodeGeneration自定义选项设置为true:

 docket.forCodeGeneration(true|false);

总而言之,当我们在springfox中为swagger-codegen生成摘要时,我们需要指定以下开关:

new Docket(DocumentationType.SWAGGER_2)
                .forCodeGeneration(true)
                .enableUrlTemplating(false)