Thanks to visit codestin.com
Credit goes to github.com

Skip to content

⚡️ Use TypeAdapter.validate_json instead of json.loads#13951

Closed
dolfinus wants to merge 1 commit into
fastapi:masterfrom
dolfinus:feature/pydanticv2-validate-json
Closed

⚡️ Use TypeAdapter.validate_json instead of json.loads#13951
dolfinus wants to merge 1 commit into
fastapi:masterfrom
dolfinus:feature/pydanticv2-validate-json

Conversation

@dolfinus

@dolfinus dolfinus commented Jul 30, 2025

Copy link
Copy Markdown
Contributor

#14962 replaced json.dumps with pydantic v2 TypeAdapter.serialize_json(). This is the same, but for body parsing - replace json.loads with TypeAdapter.validate_json().
See also #13949

Now this gives only a moderate speedup, nothing huge. The larger the request body, the larger the speedup.
Currently optimization can be applied only to POST handler with just one body field.

Small benchmark

requirements.txt

fastapi
locust
py-spy

app.py

from http import HTTPStatus

from fastapi import FastAPI, Response
from pydantic import BaseModel

app = FastAPI()

class SimpleModel(BaseModel):
    a: str


@app.post("/data")
async def create_item(data: SimpleModel):
    return Response(status_code=HTTPStatus.NO_CONTENT)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

locustfile.py

import json

from locust import FastHttpUser, TaskSet, task


class FastAPITask(TaskSet):
    data = json.dumps({"a": "abc" * 10000})
    headers = {
        "Content-Type": "application/json",
    }

    @task
    def push_data(self):
        with self.user.rest(
            "POST",
            "data",
            data=self.data,
            headers=self.headers,
            name="/data",
        ) as response:
            response.js


class FastAPIUser(FastHttpUser):
    host = "http://localhost:8000/"
    tasks = [FastAPITask]
locust --web-host=0.0.0.0 --processes 4 FastAPIUser
record --duration 600 --output flamegraph.svg -- python -m uvicorn app:app --host 0.0.0.0 --port 8000 --log-level=warning

Before - 2228RPS, json.loads took 9.8% and type_adapter.validate_python took 1% = 11% combined
fastapi_with_json_loads.tar.gz
fastapi_with_json_loads

After - 2570RPS, type_adapter.validate_json took 7.17%
fastapi_with_typeadapter_json.tar.gz
fastapi_with_typeadapter_json

Caveats - if route handle contains multiple fields with Body() annotation, json will be parsed for each field. Changing this requires substantial rewrite of body parsing, e.g. merging all body fields into one pydantic class and using it's model_validate_json() method for body parsing. I'm not ready for this type of change, so this can be considered as proof-of-concept.

Bump pydantic minimal version to 2.10.0 because of this issue with validate_json appears on versions below pydantic-core 2.24.1

@dolfinus dolfinus force-pushed the feature/pydanticv2-validate-json branch 12 times, most recently from a558ae5 to 3160247 Compare July 30, 2025 18:18
@YuriiMotov YuriiMotov changed the title ✨ Use TypeAdapter.validate_json for Pydantic v2 ♻️ Use TypeAdapter.validate_json for Pydantic v2 Aug 1, 2025
@github-actions github-actions Bot added the conflicts Automatically generated when a PR has a merge conflict label Sep 20, 2025
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

@dolfinus dolfinus force-pushed the feature/pydanticv2-validate-json branch from 3160247 to 79b4288 Compare February 23, 2026 18:50
@github-actions github-actions Bot removed the conflicts Automatically generated when a PR has a merge conflict label Feb 23, 2026
@codspeed-hq

codspeed-hq Bot commented Feb 23, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 24.77%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 2 improved benchmarks
✅ 18 untouched benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
test_sync_receiving_large_payload 12.1 ms 9.7 ms +24.64%
test_async_receiving_large_payload 11.9 ms 9.5 ms +24.9%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing dolfinus:feature/pydanticv2-validate-json (7348364) with master (59d4a80)1

Open in CodSpeed

Footnotes

  1. No successful run was found on master (dbfd55c) during the generation of this report, so 59d4a80 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@github-actions

github-actions Bot commented Feb 23, 2026

Copy link
Copy Markdown
Contributor

@dolfinus dolfinus force-pushed the feature/pydanticv2-validate-json branch from 79b4288 to 05540da Compare February 23, 2026 19:17
@dolfinus dolfinus changed the title ♻️ Use TypeAdapter.validate_json for Pydantic v2 ♻️ Use TypeAdapter.validate_json instead of json.loads Feb 23, 2026
@dolfinus dolfinus force-pushed the feature/pydanticv2-validate-json branch 3 times, most recently from 4a76701 to e26fe00 Compare February 23, 2026 21:30
@dolfinus dolfinus changed the title ♻️ Use TypeAdapter.validate_json instead of json.loads ⚡️ Use TypeAdapter.validate_json instead of json.loads Feb 23, 2026
@dolfinus dolfinus marked this pull request as ready for review February 23, 2026 21:39
@github-actions github-actions Bot added the conflicts Automatically generated when a PR has a merge conflict label Mar 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

@dolfinus dolfinus force-pushed the feature/pydanticv2-validate-json branch from e26fe00 to 2688001 Compare May 27, 2026 11:46
@github-actions github-actions Bot removed the conflicts Automatically generated when a PR has a merge conflict label May 27, 2026
@dolfinus dolfinus force-pushed the feature/pydanticv2-validate-json branch from 2688001 to 7348364 Compare May 27, 2026 12:05
@dolfinus dolfinus force-pushed the feature/pydanticv2-validate-json branch from 7348364 to 34532c6 Compare May 27, 2026 12:16
@github-actions

Copy link
Copy Markdown
Contributor

This PR modifies dependency files (pyproject.toml or uv.lock), which is restricted to members of the fastapi organization on GitHub.

If you need a dependency change, please open a discussion describing what you need and why.

Closing this PR automatically.

@github-actions github-actions Bot closed this May 27, 2026
@dolfinus

Copy link
Copy Markdown
Contributor Author

This bot is quite annoying... #15617

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants