🐛 fix: Pydantic v2/v1 models as body_schema (FastAPI migration path)
swadhinbiswas committed 2 months ago
a4cfa86
1 parent e568aae
commit a4cfa86
2 files changed
+46 -0
Showing 2 changed files+46-0
▼crates/justapi-py/python/justapi/_native_helper.py
+20-0
| @@ -217,6 +217,26 @@ def validate_body(schema_fn, body_bytes): | ||
217 | 217 | except Exception as e: # pragma: no cover - defensive |
218 | 218 | return [f"schema validation error: {e}"] |
219 | 219 | |
220 | + # Pydantic v2 model class: validate via model_json_schema() through the | |
221 | + # Rust engine (mirrors the native fast path). This makes | |
222 | + # `body_schema=SomePydanticModel` work for FastAPI migrants. | |
223 | + model_json_schema = getattr(schema_fn, "model_json_schema", None) | |
224 | + if callable(model_json_schema) and _rust_validate_value is not None: | |
225 | + try: | |
226 | + schema_json = json.dumps(model_json_schema()) | |
227 | + return _rust_validate_value(schema_json, json.dumps(body_data)) | |
228 | + except Exception as e: # pragma: no cover - defensive | |
229 | + return [f"schema validation error: {e}"] | |
230 | + | |
231 | + # Pydantic v1 model class: validate via schema(). | |
232 | + v1_schema = getattr(schema_fn, "schema", None) | |
233 | + if callable(v1_schema) and _rust_validate_value is not None: | |
234 | + try: | |
235 | + schema_json = json.dumps(v1_schema()) | |
236 | + return _rust_validate_value(schema_json, json.dumps(body_data)) | |
237 | + except Exception as e: # pragma: no cover - defensive | |
238 | + return [f"schema validation error: {e}"] | |
239 | + | |
220 | 240 | # Legacy callable schema. |
221 | 241 | result = schema_fn(body_data) |
222 | 242 | if result is None: |
223 | 243 | |
▼crates/justapi-py/python/justapi/test_native.py
+26-0
| @@ -296,3 +296,29 @@ def test_run_defaults_to_localhost_8000(): | ||
296 | 296 | s.close() |
297 | 297 | except Exception: |
298 | 298 | pass |
299 | + | |
300 | + | |
301 | +def test_pydantic_model_as_body_schema(): | |
302 | + """Pydantic v2 models work as body_schema (validated via their JSON | |
303 | + Schema in the Rust engine) — FastAPI-migration path (fixed 2026-08-08).""" | |
304 | + from pydantic import BaseModel, Field | |
305 | + from justapi import JustAPIApp, JustAPITestClient | |
306 | + | |
307 | + class Pet(BaseModel): | |
308 | + name: str = Field(..., min_length=1) | |
309 | + species: str | |
310 | + | |
311 | + app = JustAPIApp() | |
312 | + | |
313 | + @app.post("/pets", body_schema=Pet) | |
314 | + def create(request): | |
315 | + body = request.json() | |
316 | + return {"name": body["name"], "species": body["species"]} | |
317 | + | |
318 | + c = JustAPITestClient(app) | |
319 | + ok = c.post("/pets", b'{"name": "rex", "species": "dog"}') | |
320 | + empty = c.post("/pets", b'{"name": "", "species": "dog"}') | |
321 | + wrong = c.post("/pets", b'{"name": 123, "species": "dog"}') | |
322 | + assert ok["status"] == 200, ok | |
323 | + assert empty["status"] == 422, empty | |
324 | + assert wrong["status"] == 422, wrong | |
299 | 325 | |