我正在使用带有flask 1.1.2、apispec 5.1.1、marshmallow 数据类8.3.2 和flask_apispec 0.11.0 的python 3.8。基本代码如下所示: 我有一个对象(项目)的 marshamlow 数据类,该对象(项目)包含一个可选对象(所有者)。然后,对于我的最终端点,我需要发送这些项目的列表。
下面是一个最小的工作示例,一个端点获取具有可选所有者的项目,一个端点获取项目列表(具有可选所有者)。项目端点的 swagger 文档显示了所有者及其特征。投资组合的端点无法正确呈现 swagger 文档,并且仅显示所有者的空括号。我不知道这是否是 a)按预期工作(我只是不应该嵌套对象),b)apispec 的渲染问题或 c)由 flask_apispec 引起的(swagger.json)组合问题,并且会感谢任何人指出我为什么它不起作用的方向。
我尝试过使用 OpenApi 2.0 和 3.0 标准,但两者都遇到了同样的问题。对于值得验证的内容和实际的 API 行为似乎按预期工作,这只是一个招摇的问题
最小代码示例:
from typing import Optional
from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from flask_apispec.extension import FlaskApiSpec
from flask_apispec import use_kwargs
from flask import Flask, request
from marshmallow_dataclass import dataclass, List
@dataclass
class Owner:
email: str = field(metadata={'example': 'ac@d.com', 'default': 'b@g.com'})
age: int = field(metadata={'example': 12, 'default': 12})
name: str = field(metadata={'example': 'me', 'default': 'bla'})
@dataclass
class Item:
color: str
owner: Optional[Owner]
@dataclass
class PortfolioOfItems:
assets: List[Item] = field(metadata={'default_factory': lambda: []})
purchase_year: int
def create_app():
app = Flask(__name__)
apispecs = APISpec(
title='api',
version='2.3',
openapi_version="3.0.0",
plugins=[MarshmallowPlugin()],
)
app.config.update({
'APISPEC_SPEC': apispecs,
'APISPEC_SWAGGER_URL': '/swagger.json',
'APISPEC_SWAGGER_UI_URL': '/apidocs/'
})
portfolio_schema = PortfolioOfItems.Schema()
item_schema = Item.Schema()
@use_kwargs(portfolio_schema)
@app.route("/v1/portfolio", methods=["POST"])
def portfolio():
input_data = portfolio_schema.loads(request.data)
owners = [i.owner for i in input_data if hasattr(i, 'owner')]
result = {"result": owners}
return result
@use_kwargs(item_schema)
@app.route("/v1/item", methods=["POST"])
def item():
print(request.data)
input_data = item_schema.loads(request.data)
owner = getattr(input_data, 'owner', None)
result = {"result": owner}
return result
docs = FlaskApiSpec(app)
docs.register(portfolio)
docs.register(item)
return app
if __name__ == '__main__':
api = create_app()
api.run(port=4999)
为 swagger 文档生成的 json 文件(openapi 3.0):
"components": {
"schemas": {
"Item": {
"properties": {
"color": {
"type": "string"
},
"owner": {
"allOf": [
{
"$ref": "#/components/schemas/Owner"
}
],
"default": null,
"nullable": true
}
},
"required": [
"color"
],
"type": "object"
},
"Owner": {
"properties": {
"age": {
"example": 12,
"type": "integer"
},
"email": {
"example": "ac@d.com",
"type": "string"
},
"name": {
"example": "me",
"type": "string"
}
},
"required": [
"age",
"email",
"name"
],
"type": "object"
},
"PortfolioOfItems": {
"properties": {
"assets": {
"items": {
"$ref": "#/components/schemas/Item"
},
"type": "array"
},
"purchase_year": {
"type": "integer"
}
},
"required": [
"assets",
"purchase_year"
],
"type": "object"
}
}
},
"info": {
"title": "api",
"version": "2.3"
},
"openapi": "3.0.0",
"paths": {
"/v1/item": {
"options": {
"parameters": [
{
"in": "body",
"name": "body",
"required": false,
"schema": {
"$ref": "#/components/schemas/Item"
}
}
],
"responses": {}
},
"post": {
"parameters": [
{
"in": "body",
"name": "body",
"required": false,
"schema": {
"$ref": "#/components/schemas/Item"
}
}
],
"responses": {}
}
},
"/v1/portfolio": {
"options": {
"parameters": [
{
"in": "body",
"name": "body",
"required": false,
"schema": {
"$ref": "#/components/schemas/PortfolioOfItems"
}
}
],
"responses": {}
},
"post": {
"parameters": [
{
"in": "body",
"name": "body",
"required": false,
"schema": {
"$ref": "#/components/schemas/PortfolioOfItems"
}
}
],
"responses": {}
}
}
}```