prefer-native-string-check
Avoid unconstrained adapters for string assertions or already encoded JSON mappings.
Why
A plain string adapter obscures an assertion and can decode bytes. Generic JSON-dictionary validation after encoding adds a separate runtime contract, often only to satisfy an annotation; it can reject nested integer keys that a response serializer accepts and does not prove response serializability.
Fix
Use isinstance(value, str) for string assertions. For annotation-only JSON adaptation, return a typed Response/JSONResponse at the serialization boundary. Keep structured input and specific schema validation. Preserve intentional coercion, recursive string-key validation or ValidationError contracts explicitly.
Examples
from pydantic import TypeAdapter
def test_receipt(): assert TypeAdapter(str).validate_python(receipt["id"]) == "abc"def test_receipt(): value = receipt["id"] assert isinstance(value, str) assert value == "abc"from pydantic import TypeAdapter, JsonValuefrom fastapi.encoders import jsonable_encoder
def response_content(body): return TypeAdapter(dict[str, JsonValue]).validate_python( jsonable_encoder( {"body": body}, custom_encoder={ bytes: lambda value: value.decode("utf-8", errors="replace") }, ) )from fastapi.encoders import jsonable_encoderfrom fastapi.responses import JSONResponse
def response(body) -> JSONResponse: return JSONResponse(content=jsonable_encoder({"body": body}))