Browse Source

🐛 Fix using `Json[list[str]]` type (issue #10997) (#14616)

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Motov Yurii <[email protected]>
Co-authored-by: Sebastián Ramírez <[email protected]>
pull/14840/head
Kanetsuna Masaya 4 months ago
committed by GitHub
parent
commit
c5fd75a321
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 12
      fastapi/dependencies/utils.py
  2. 63
      tests/test_json_type.py

12
fastapi/dependencies/utils.py

@ -51,7 +51,7 @@ from fastapi.logger import logger
from fastapi.security.oauth2 import SecurityScopes from fastapi.security.oauth2 import SecurityScopes
from fastapi.types import DependencyCacheKey from fastapi.types import DependencyCacheKey
from fastapi.utils import create_model_field, get_path_param_names from fastapi.utils import create_model_field, get_path_param_names
from pydantic import BaseModel from pydantic import BaseModel, Json
from pydantic.fields import FieldInfo from pydantic.fields import FieldInfo
from starlette.background import BackgroundTasks as StarletteBackgroundTasks from starlette.background import BackgroundTasks as StarletteBackgroundTasks
from starlette.concurrency import run_in_threadpool from starlette.concurrency import run_in_threadpool
@ -726,11 +726,19 @@ def _validate_value_with_model_field(
return v_, [] return v_, []
def _is_json_field(field: ModelField) -> bool:
return any(type(item) is Json for item in field.field_info.metadata)
def _get_multidict_value( def _get_multidict_value(
field: ModelField, values: Mapping[str, Any], alias: Union[str, None] = None field: ModelField, values: Mapping[str, Any], alias: Union[str, None] = None
) -> Any: ) -> Any:
alias = alias or get_validation_alias(field) alias = alias or get_validation_alias(field)
if is_sequence_field(field) and isinstance(values, (ImmutableMultiDict, Headers)): if (
(not _is_json_field(field))
and is_sequence_field(field)
and isinstance(values, (ImmutableMultiDict, Headers))
):
value = values.getlist(alias) value = values.getlist(alias)
else: else:
value = values.get(alias, None) value = values.get(alias, None)

63
tests/test_json_type.py

@ -0,0 +1,63 @@
import json
from typing import Annotated
from fastapi import Cookie, FastAPI, Form, Header, Query
from fastapi.testclient import TestClient
from pydantic import Json
app = FastAPI()
@app.post("/form-json-list")
def form_json_list(items: Annotated[Json[list[str]], Form()]) -> list[str]:
return items
@app.get("/query-json-list")
def query_json_list(items: Annotated[Json[list[str]], Query()]) -> list[str]:
return items
@app.get("/header-json-list")
def header_json_list(x_items: Annotated[Json[list[str]], Header()]) -> list[str]:
return x_items
@app.get("/cookie-json-list")
def cookie_json_list(items: Annotated[Json[list[str]], Cookie()]) -> list[str]:
return items
client = TestClient(app)
def test_form_json_list():
response = client.post(
"/form-json-list", data={"items": json.dumps(["abc", "def"])}
)
assert response.status_code == 200, response.text
assert response.json() == ["abc", "def"]
def test_query_json_list():
response = client.get(
"/query-json-list", params={"items": json.dumps(["abc", "def"])}
)
assert response.status_code == 200, response.text
assert response.json() == ["abc", "def"]
def test_header_json_list():
response = client.get(
"/header-json-list", headers={"x-items": json.dumps(["abc", "def"])}
)
assert response.status_code == 200, response.text
assert response.json() == ["abc", "def"]
def test_cookie_json_list():
client.cookies.set("items", json.dumps(["abc", "def"]))
response = client.get("/cookie-json-list")
assert response.status_code == 200, response.text
assert response.json() == ["abc", "def"]
client.cookies.clear()
Loading…
Cancel
Save