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

Python
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}") if pydantic_object isn't actually a BaseModel subclass.

On success, stores self.pydantic_object and constructs self._json_parser = JSONOutputParser(pydantic_model=pydantic_object).

Public Methods

parse

Python
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.

Python · 11 lines
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

Python
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

Python
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

Python
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.

Python · 2 lines
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, returns field_info["type"] if present directly; else for anyOf unions, 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 hardcoded EXAMPLES map keyed by JSON-schema type name ("string"→"example", "integer"→1, "number"→1.0, "boolean"→True, "array"→[], "object"→{}; unresolvable types get None), then json.dumpss it with indent=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

Python · 33 lines
# 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 want get_schema(), validate(), and the richer per-field get_format_instructions() output — functionally the parsing behavior is identical (this class delegates to JSONOutputParser internally), 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 dataclass or TypedDict instead of a Pydantic BaseModel — raises TypeError immediately, since the constructor explicitly checks issubclass(pydantic_object, BaseModel).
  • Expecting get_format_instructions() to be identical to JSONOutputParser's version — it's a separate, more detailed implementation with its own field-description formatting logic.

Version History

Not determinable from source.

Related pages