alibaba / pont

🌉数据服务层解决方案
MIT License
3.03k stars 254 forks source link

SwaggerV3不支持AnyOf数据类型 #435

Open qixm-burnish opened 2 weeks ago

qixm-burnish commented 2 weeks ago

What happens(发生了什么)?

SwaggerV3 JSON文档生成时,api.d.ts中的AnyOf类型字段会被直接生成any。具体对比如下:

screenshot-20240905-151108.jpg

另外还有以下两种特殊情况: 1、生成类型错误: 对于ValidationError的定义如下:

  "ValidationError": {
      "properties": {
          "loc": {
              "items": {
                  "anyOf": [
                      {
                          "type": "string"
                      },
                      {
                          "type": "integer"
                      }
                  ]
              },
              "type": "array",
              "title": "Location"
          },
          "msg": {
              "type": "string",
              "title": "Message"
          },
          "type": {
              "type": "string",
              "title": "Error Type"
          }
      },
      "type": "object",
      "required": [
          "loc",
          "msg",
          "type"
      ],
      "title": "ValidationError"
  }

生成的错误类型如下:

export class ValidationError {
  /** loc ---------------array类型错误 ----------- */
  loc: array

  /** msg */
  msg: string

  /** type */
  type: string
}

2、这种特殊结构也需要单独处理:

"vehicle_series_ids": {
  "anyOf": [
    {
      "items": {
        "type": "integer"
      },
      "type": "array"
    },
    {
      "type": "null"
    }
  ],
  "title": "Vehicle Series Ids",
  "description": "车系id列表, None时为全部"
},

How To Reproduce(如何重现)

完整的Swagger文档如下:

{
    "openapi": "3.1.0",
    "info": {
        "title": "FastAPI API Docs",
        "description": "FastAPI todo swagger",
        "version": "1.0.0"
    },
    "paths": {
        "/todo/": {
            "get": {
                "tags": [
                    "todo"
                ],
                "summary": "Get Todo List",
                "operationId": "get_todo_list_todo__get",
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/TodoListResponse"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/todo/{id}": {
            "post": {
                "tags": [
                    "todo"
                ],
                "summary": "Get Todo List",
                "operationId": "get_todo_list_todo__id__post",
                "parameters": [
                    {
                        "description": "Todo的id",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "title": "Todo的id",
                            "description": "Todo的id"
                        },
                        "name": "id",
                        "in": "path"
                    }
                ],
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/TodoItem"
                            }
                        }
                    },
                    "required": true
                },
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {}
                            }
                        }
                    },
                    "422": {
                        "description": "Validation Error",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/HTTPValidationError"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/": {
            "get": {
                "summary": "Index",
                "operationId": "index__get",
                "responses": {
                    "200": {
                        "description": "Successful Response",
                        "content": {
                            "application/json": {
                                "schema": {}
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "HTTPValidationError": {
                "properties": {
                    "detail": {
                        "items": {
                            "$ref": "#/components/schemas/ValidationError"
                        },
                        "type": "array",
                        "title": "Detail"
                    }
                },
                "type": "object",
                "title": "HTTPValidationError"
            },
            "Role": {
                "properties": {
                    "id": {
                        "type": "integer",
                        "title": "Id"
                    },
                    "role_name": {
                        "type": "string",
                        "title": "Role Name"
                    }
                },
                "type": "object",
                "required": [
                    "id",
                    "role_name"
                ],
                "title": "Role"
            },
            "TodoItem": {
                "properties": {
                    "id": {
                        "type": "integer",
                        "title": "Id"
                    },
                    "title": {
                        "type": "string",
                        "title": "Title"
                    },
                    "completed": {
                        "type": "boolean",
                        "title": "Completed"
                    },
                    "complete_at": {
                        "type": "string",
                        "format": "date-time",
                        "title": "Complete At"
                    },
                    "creator": {
                        "$ref": "#/components/schemas/User"
                    },
                    "field1": {
                        "anyOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "integer"
                            }
                        ],
                        "title": "Field1"
                    },
                    "field2": {
                        "anyOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "integer"
                            }
                        ],
                        "title": "Field2"
                    },
                    "field3": {
                        "anyOf": [
                            {
                                "type": "string"
                            },
                            {
                                "type": "integer"
                            }
                        ],
                        "title": "Field3"
                    },
                    "field4": {
                        "items": {
                            "type": "string"
                        },
                        "type": "array",
                        "title": "Field4"
                    },
                    "field5": {
                        "type": "boolean",
                        "title": "Field5"
                    },
                    "field6": {
                        "type": "boolean",
                        "title": "Field6",
                        "default": true
                    },
                    "field7": {
                        "type": "boolean",
                        "title": "Field7",
                        "description": "是否为营运, None时为全部"
                    }
                },
                "type": "object",
                "required": [
                    "id",
                    "title",
                    "completed",
                    "complete_at",
                    "field1"
                ],
                "title": "TodoItem"
            },
            "TodoListResponse": {
                "properties": {
                    "data": {
                        "items": {
                            "$ref": "#/components/schemas/TodoItem"
                        },
                        "type": "array",
                        "title": "Data"
                    },
                    "page": {
                        "type": "integer",
                        "title": "Page"
                    },
                    "page_size": {
                        "type": "integer",
                        "title": "Page Size"
                    },
                    "total": {
                        "type": "integer",
                        "title": "Total"
                    }
                },
                "type": "object",
                "required": [
                    "data",
                    "page",
                    "page_size",
                    "total"
                ],
                "title": "TodoListResponse"
            },
            "User": {
                "properties": {
                    "id": {
                        "type": "integer",
                        "title": "Id"
                    },
                    "username": {
                        "type": "string",
                        "title": "Username"
                    },
                    "role": {
                        "$ref": "#/components/schemas/Role"
                    }
                },
                "type": "object",
                "required": [
                    "id",
                    "username"
                ],
                "title": "User"
            },
            "ValidationError": {
                "properties": {
                    "loc": {
                        "items": {
                            "anyOf": [
                                {
                                    "type": "string"
                                },
                                {
                                    "type": "integer"
                                }
                            ]
                        },
                        "type": "array",
                        "title": "Location"
                    },
                    "msg": {
                        "type": "string",
                        "title": "Message"
                    },
                    "type": {
                        "type": "string",
                        "title": "Error Type"
                    }
                },
                "type": "object",
                "required": [
                    "loc",
                    "msg",
                    "type"
                ],
                "title": "ValidationError"
            }
        }
    }
}