model_validate_json
model_validate_json is a Pydantic method that reads JSON text and builds a checked model from it, raising ValidationError when anything is wrong.
Last updated: 30 Sep, 2026 · Python 3.14 · Pydantic 2.12
try and except caught answers that were not JSON. An answer can also be perfect JSON with the wrong values in it. The Triage model from Pydantic models catches both in one step.
Syntax:
result = Model.model_validate_json(json_text)Checking one answer
Keep tickets.json from JSON in the same folder; the code below reads it.
from typing import Literal
from pydantic import BaseModel, Field
class Triage(BaseModel):
category: Literal["billing", "shipping", "other"]
priority: int = Field(ge=1, le=5)import json
def ask_model(ticket_text):
text = ticket_text.lower()
if "charged" in text or "refund" in text:
return '{"category": "billing", "priority": 4}'
if "parcel" in text or "arrived" in text:
return '{"category": "shipping", "priority": 3}'
return "I am not sure how to sort this one."
with open("tickets.json") as f:
tickets = json.load(f)answer = ask_model("I was charged twice for one order")
result = Triage.model_validate_json(answer)
print(result)
print(result.category)category='billing' priority=4 billing
model_validate_json takes the answer text, reads it as JSON, and builds a Triage from it, checking every field on the way. It replaces json.loads plus your own checks.
Catching both kinds of wrong answer
from pydantic import ValidationError
for answer in ["I am not sure how to sort this one.", '{"category": "sales", "priority": 9}']:
try:
Triage.model_validate_json(answer)
except ValidationError as error:
print(error)
print("---")1 validation error for Triage
Invalid JSON: expected ident at line 1 column 2 [type=json_invalid, input_value='I am not sure how to sort this one.', input_type=str]
For further information visit https://errors.pydantic.dev/2.12/v/json_invalid
---
2 validation errors for Triage
category
Input should be 'billing', 'shipping' or 'other' [type=literal_error, input_value='sales', input_type=str]
For further information visit https://errors.pydantic.dev/2.12/v/literal_error
priority
Input should be less than or equal to 5 [type=less_than_equal, input_value=9, input_type=int]
For further information visit https://errors.pydantic.dev/2.12/v/less_than_equal
---The first is not JSON at all, and the error says Invalid JSON. The second is valid JSON that breaks both rules. Either way it is one exception, ValidationError, so one except handles both.
View the code here
[
{
"id": 1,
"customer": "Asha",
"text": "I was charged twice for one order"
},
{
"id": 2,
"customer": "Ben",
"text": "My parcel has not arrived"
},
{
"id": 3,
"customer": "Chen",
"text": "Can I get a refund for the blue mug?"
},
{
"id": 4,
"customer": "Dara",
"text": "How do I change my password?"
},
{
"id": 5,
"customer": "Eli",
"text": "The parcel arrived but the box was crushed"
}
]
Checking every ticket
checked = []
for ticket in tickets:
try:
result = Triage.model_validate_json(ask_model(ticket["text"]))
except ValidationError:
print(ticket["id"], "needs a person")
continue
checked.append(result)
print(ticket["id"], result.category, result.priority)
print(len(checked), "checked")1 billing 4 2 shipping 3 3 billing 4 4 needs a person 5 shipping 3 4 checked
Four tickets pass and ticket 4 goes to a person, with no json.loads and no hand-written range check.
Telling the model the shape
Many model APIs accept a JSON Schema, a description of the shape an answer must have, and use it to steer the model. Pydantic writes one from your class:
import json
print(json.dumps(Triage.model_json_schema(), indent=2)){
"properties": {
"category": {
"enum": [
"billing",
"shipping",
"other"
],
"title": "Category",
"type": "string"
},
"priority": {
"maximum": 5,
"minimum": 1,
"title": "Priority",
"type": "integer"
}
},
"required": [
"category",
"priority"
],
"title": "Triage",
"type": "object"
}The allowed categories and the 1 to 5 limit are all in there. When a framework says it supports structured output with a Pydantic class, this schema is what it sends.
json.loads vs model_validate_json
json.loads | Triage.model_validate_json | |
|---|---|---|
| Gives back | A dictionary | A Triage object |
| Not JSON | JSONDecodeError | ValidationError |
| JSON with a bad value | Accepted | ValidationError |
Where model_validate_json shows up in AI code
- Right after every model call that was asked for JSON.
- Reading a JSON file of settings or test cases into typed objects.
```json ... ```, fails the check as Invalid JSON. Ask for JSON only in the prompt, and treat a failure as a ticket for a person, as the loop above does.Related
- Previous: Pydantic models
- Next: async and await
- Reference: JSON in the Pydantic docs
- Make
ask_modelreturn priority 7 for shipping tickets and run the loop again. - Print
error.errors()instead oferrorinside theexcept. - Add
"account"to the Literal and a password branch toask_model.
Little by little, you're building something great.