Output Parsers
LangChain has four ways to get structured output — and three of them are the wrong choice most of the time. This article maps the decision: when to use with_structured_output(), when JsonOutputParser is still the right tool, and what to do with the legacy parsers you inherited.
Quick Reference
- →with_structured_output() is the default for typed extraction — uses native tool calling, fails loudly, no prompt engineering required
- →create_agent(response_format=...) is the v1 agent-level equivalent — ToolStrategy or ProviderStrategy, not parsers
- →StrOutputParser extracts .content as a plain string — not deprecated, use it for every text-output chain
- →JsonOutputParser is the only parser worth reaching for in new code — streaming partial JSON from models without tool calling
- →PydanticOutputParser is legacy — moved to langchain-classic, prompt-injected format instructions, fails silently
- →Tool calling fails loudly (schema validation error); prompt-based parsing fails silently (wrong shape, no exception)
- →JsonOutputParser has a diff=True mode that yields JSONPatch operations — useful for diffing incremental UI updates
- →Output parsers are Runnables — compose them with | in LCEL chains
The Four Ways to Get Structured Output
LangChain v1 has four distinct mechanisms for getting structured data out of a model. They are not interchangeable — each targets a different situation, and using the wrong one in production will cost you debugging time you don't have.
| Mechanism | What it does | Status | Use when |
|---|---|---|---|
| with_structured_output() | Wraps the model with a schema; uses native tool calling or provider JSON mode | Current — preferred | You need typed output from any modern model |
| create_agent(response_format=...) | Structured output baked into the agent loop — ToolStrategy or ProviderStrategy | Current — v1 agents only | Building an agent that must return a typed response |
| JsonOutputParser | Parses model text as JSON; streams partial objects incrementally | Current — limited scope | Streaming partial JSON from models without tool calling |
| StrOutputParser | Extracts .content as a plain string | Current — always valid | Any chain that returns text |
| PydanticOutputParser | Injects format instructions into the prompt; parses text response | Legacy — langchain-classic | Maintaining old code; model doesn't support tool calling |
The reason three of these exist at all is history, not design. Output parsers predate tool calling. When GPT-3 was the frontier model, the only way to get JSON was to ask nicely and hope. Tool calling changed that — models now have a native JSON output path that is schema-validated and far more reliable. LangChain v1 codifies this: structured output strategies are first-class, parsers are backward compatibility.
Start at the top — exit at the first match