PydanticOutputParser (pydantic_parser.py)
On this page
class output_parser.pydantic_parser.PydanticOutputParser(BaseOutputParser)
Overview
Parses LLM output into a fully validated Pydantic model instance, combining JSONOutputParser's robust extraction with Pydantic's type coercion, nested models, and custom validators. Thin wrapper: internally delegates all extraction/parsing work to an internal JSONOutputParser(pydantic_model=pydantic_object) instance.
Depends on base_parser.py, json_parser.py (JSONOutputParser), and pydantic (required — unlike YAMLOutputParser, whose ImportError is raised eagerly, this class checks PYDANTIC_AVAILABLE and raises the same way at construction time).
Constructor
PydanticOutputParser(pydantic_object: Type[T])
Raises:
ImportError("Pydantic is required for PydanticOutputParser. Install it with: pip install pydantic")if pydantic isn't installed.TypeError(f"pydantic_object must be a Pydantic BaseModel subclass. Got: {type}")ifpydantic_objectisn't actually aBaseModelsubclass.
On success, stores self.pydantic_object and constructs self._json_parser = JSONOutputParser(pydantic_model=pydantic_object).
Public Methods
parse
def parse(self, text: str) -> T
Returns: a validated instance of pydantic_object.
Raises: ParsingError — either propagated directly from self._json_parser.parse(text) (re-raised unchanged, since the except ParsingError: raise clause comes first), or wrapped as ParsingError(f"Failed to parse into {name}: {e}", cause=e) for any other, non-ParsingError exception type.
from pydantic import BaseModel, Field
class Product(BaseModel):
name: str = Field(..., description="Product name")
price: float = Field(..., ge=0, description="Price in USD")
in_stock: bool = Field(default=True)
parser = PydanticOutputParser(pydantic_object=Product)
text = '{"name": "Widget", "price": 9.99}'
product = parser.parse(text)
# Product(name='Widget', price=9.99, in_stock=True)
get_format_instructions
def get_format_instructions(self) -> str
More detailed than JSONOutputParser's own version — builds a per-field bulleted description (• field_name (type, required|optional): description) using _resolve_type to render human-readable type names (including union types via anyOf, and $ref-based nested model names), plus a generated example JSON block via _generate_example().
get_schema
def get_schema(self) -> Dict[str, Any]
Returns the raw self.pydantic_object.model_json_schema() dict — useful if you need the schema for purposes beyond prompt instructions (e.g. building your own UI form, or feeding to a different LLM API's native "response_format" / structured-output parameter).
validate
def validate(self, data: Dict[str, Any]) -> T
Validates an already-parsed dict directly (bypasses text extraction entirely) — useful when you have a dict from another source (e.g. a tool call's arguments, or a different parser's output) and just want Pydantic validation applied.
Raises: ParsingError(f"Validation failed for {name}: {e}", original_text=str(data), cause=e) if pydantic_object(**data) raises.
parser = PydanticOutputParser(pydantic_object=Product)
product = parser.validate({"name": "Gadget", "price": 19.99})
Private Helpers
_resolve_type(field_info) -> str(static) — for JSON-schema field info, returnsfield_info["type"]if present directly; else foranyOfunions, joins the non-null member types with" | "; else for$ref, extracts the model name from the ref path; else"any"._generate_example() -> str— builds a minimal example dict using a hardcodedEXAMPLESmap keyed by JSON-schema type name ("string"→"example","integer"→1,"number"→1.0,"boolean"→True,"array"→[],"object"→{}; unresolvable types getNone), thenjson.dumpss it withindent=2.
Complexity & Thread Safety
Identical characteristics to JSONOutputParser for the extraction step, plus whatever complexity pydantic_object's own validators add (governed by your model's definition, not this library). Safe to share across threads — no mutable state beyond the read-only pydantic_object/_json_parser.
Side Effects
None beyond raising exceptions — delegates entirely to JSONOutputParser, which itself has no side effects.
Examples
# Basic
from pydantic import BaseModel
class Answer(BaseModel):
text: str
confidence: float
parser = PydanticOutputParser(pydantic_object=Answer)
result = parser.parse('{"text": "Paris", "confidence": 0.9}')
# Answer(text='Paris', confidence=0.9)
# Intermediate — nested model
class Source(BaseModel):
url: str
reliability: float
class ResearchAnswer(BaseModel):
text: str
sources: list[Source]
parser = PydanticOutputParser(pydantic_object=ResearchAnswer)
parser.parse('{"text": "...", "sources": [{"url": "...", "reliability": 0.8}]}')
# Advanced — validating a pre-parsed dict from elsewhere
tool_args = {"name": "Widget", "price": 9.99}
product = PydanticOutputParser(pydantic_object=Product).validate(tool_args)
# Error handling
try:
parser.parse('{"text": "Paris"}') # missing required 'confidence'
except ParsingError as e:
print(str(e))
# Production usage — schema introspection for logging/observability
parser = PydanticOutputParser(pydantic_object=Answer)
schema = parser.get_schema()
log_expected_shape(schema)
Best Practices
- Prefer this over raw
JSONOutputParser(pydantic_model=...)when you also wantget_schema(),validate(), and the richer per-fieldget_format_instructions()output — functionally the parsing behavior is identical (this class delegates toJSONOutputParserinternally), so pick based on which surface API you need. - Use
.validate()rather than.parse()when you already have structured data (e.g. from a tool-call JSON payload) and don't need text extraction — it skips the JSON-extraction step entirely.
Common Mistakes
- Constructing this with a plain
dataclassorTypedDictinstead of a PydanticBaseModel— raisesTypeErrorimmediately, since the constructor explicitly checksissubclass(pydantic_object, BaseModel). - Expecting
get_format_instructions()to be identical toJSONOutputParser's version — it's a separate, more detailed implementation with its own field-description formatting logic.
Related APIs
JSONOutputParser— wrapped internally by this class.BaseOutputParser,ParsingErrorschema.pyPydantic schemas —AnswerSchema,ToolCallSchema, etc. can all be used aspydantic_objecthere.
Version History
Not determinable from source.