]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
:bug: Fix JSON Schema of additional properties (#121)
authorSebastián Ramírez <tiangolo@gmail.com>
Fri, 29 Mar 2019 11:15:49 +0000 (15:15 +0400)
committerGitHub <noreply@github.com>
Fri, 29 Mar 2019 11:15:49 +0000 (15:15 +0400)
#87

fastapi/openapi/models.py
tests/test_additional_properties.py [new file with mode: 0644]

index 6572c7c07239939e414561ff6e1859410d3f123f..a045bdf704ac68b09bcba53a59500274dc52f325 100644 (file)
@@ -99,7 +99,7 @@ class SchemaBase(BaseModel):
     not_: Optional[List[Any]] = PSchema(None, alias="not")  # type: ignore
     items: Optional[Any] = None
     properties: Optional[Dict[str, Any]] = None
-    additionalProperties: Optional[Union[bool, Any]] = None
+    additionalProperties: Optional[Union[Dict[str, Any], bool]] = None
     description: Optional[str] = None
     format: Optional[str] = None
     default: Optional[Any] = None
@@ -120,7 +120,7 @@ class Schema(SchemaBase):
     not_: Optional[List[SchemaBase]] = PSchema(None, alias="not")  # type: ignore
     items: Optional[SchemaBase] = None
     properties: Optional[Dict[str, SchemaBase]] = None
-    additionalProperties: Optional[Union[bool, SchemaBase]] = None
+    additionalProperties: Optional[Union[SchemaBase, bool]] = None
 
 
 class Example(BaseModel):
@@ -220,7 +220,7 @@ class Operation(BaseModel):
     operationId: Optional[str] = None
     parameters: Optional[List[Union[Parameter, Reference]]] = None
     requestBody: Optional[Union[RequestBody, Reference]] = None
-    responses: Union[Responses, Dict[Union[str], Response]]
+    responses: Union[Responses, Dict[str, Response]]
     # Workaround OpenAPI recursive reference
     callbacks: Optional[Dict[str, Union[Dict[str, Any], Reference]]] = None
     deprecated: Optional[bool] = None
diff --git a/tests/test_additional_properties.py b/tests/test_additional_properties.py
new file mode 100644 (file)
index 0000000..cf39c8e
--- /dev/null
@@ -0,0 +1,110 @@
+from typing import Dict
+
+from fastapi import FastAPI
+from pydantic import BaseModel
+from starlette.testclient import TestClient
+
+app = FastAPI()
+
+
+class Items(BaseModel):
+    items: Dict[str, int]
+
+
+@app.post("/foo")
+def foo(items: Items):
+    return items.items
+
+
+client = TestClient(app)
+
+
+openapi_schema = {
+    "openapi": "3.0.2",
+    "info": {"title": "Fast API", "version": "0.1.0"},
+    "paths": {
+        "/foo": {
+            "post": {
+                "responses": {
+                    "200": {
+                        "description": "Successful Response",
+                        "content": {"application/json": {"schema": {}}},
+                    },
+                    "422": {
+                        "description": "Validation Error",
+                        "content": {
+                            "application/json": {
+                                "schema": {
+                                    "$ref": "#/components/schemas/HTTPValidationError"
+                                }
+                            }
+                        },
+                    },
+                },
+                "summary": "Foo Post",
+                "operationId": "foo_foo_post",
+                "requestBody": {
+                    "content": {
+                        "application/json": {
+                            "schema": {"$ref": "#/components/schemas/Items"}
+                        }
+                    },
+                    "required": True,
+                },
+            }
+        }
+    },
+    "components": {
+        "schemas": {
+            "Items": {
+                "title": "Items",
+                "required": ["items"],
+                "type": "object",
+                "properties": {
+                    "items": {
+                        "title": "Items",
+                        "type": "object",
+                        "additionalProperties": {"type": "integer"},
+                    }
+                },
+            },
+            "ValidationError": {
+                "title": "ValidationError",
+                "required": ["loc", "msg", "type"],
+                "type": "object",
+                "properties": {
+                    "loc": {
+                        "title": "Location",
+                        "type": "array",
+                        "items": {"type": "string"},
+                    },
+                    "msg": {"title": "Message", "type": "string"},
+                    "type": {"title": "Error Type", "type": "string"},
+                },
+            },
+            "HTTPValidationError": {
+                "title": "HTTPValidationError",
+                "type": "object",
+                "properties": {
+                    "detail": {
+                        "title": "Detail",
+                        "type": "array",
+                        "items": {"$ref": "#/components/schemas/ValidationError"},
+                    }
+                },
+            },
+        }
+    },
+}
+
+
+def test_additional_properties_schema():
+    response = client.get("/openapi.json")
+    assert response.status_code == 200
+    assert response.json() == openapi_schema
+
+
+def test_additional_properties_post():
+    response = client.post("/foo", json={"items": {"foo": 1, "bar": 2}})
+    assert response.status_code == 200
+    assert response.json() == {"foo": 1, "bar": 2}