CloudCodeTree LogoCloudCodeTree
AI NewsTutorialsAbout
CloudCodeTree Logo
CloudCodeTree
  • AI News
  • Tutorials
  • About
← Back to AI News
Stop Parsing Markdown: Use Claude's Structured Outputs for Schema-Valid JSON Every Time

Stop Parsing Markdown: Use Claude's Structured Outputs for Schema-Valid JSON Every Time

Chris Harper

2 min read

Jul 15, 2026 · 20:08 UTC

AI
Workflow
Best Practices
Claude Code
Agents

TL;DR: Prompting Claude for JSON works ~70% of the time; structured outputs use schema-constrained decoding to make it work 99.9%+ of the time — no parsing retries, no markdown-wrapped surprises.

Asking Claude to "respond with JSON only" fails in the edge cases that matter most: markdown wrapping, extra commentary, mismatched keys. Two built-in features constrain generation at the token level and eliminate the failure mode.

Pattern 1: output_format for direct JSON responses

The Python SDK's .messages.parse() accepts a Pydantic model and returns a .parsed_output that's already deserialized and validated:

from pydantic import BaseModel
from anthropic import Anthropic

class Ticket(BaseModel):
    title: str
    priority: str   # "low" | "medium" | "high"
    labels: list[str]

client = Anthropic()
resp = client.messages.parse(
    model="claude-haiku-4-5",
    max_tokens=512,
    messages=[{"role": "user", "content": "Triage: login button broken on Safari."}],
    output_format=Ticket,
)
print(resp.parsed_output)
# Ticket(title='Login button broken on Safari', priority='medium', labels=['bug', 'safari'])

No json.loads(), no try/except, no retry loop. The SDK strips the code block, parses, validates.

Pattern 2: strict: true on tool definitions

When Claude calls your functions (the tool-use loop), strict: true guarantees the input block exactly matches your schema — no extra fields, no missing required fields:

tools = [{
    "name": "create_ticket",
    "strict": True,
    "input_schema": {
        "type": "object",
        "properties": {
            "title": {"type": "string"},
            "priority": {"type": "string", "enum": ["low", "medium", "high"]},
        },
        "required": ["title", "priority"],
        "additionalProperties": False,   # required for strict mode
    }
}]

Key tips

  • Always set additionalProperties: false — strict mode requires it on every object
  • Schema caching: the first request with a new schema compiles a grammar (a few hundred ms of extra latency); subsequent requests with the same schema are cached for 24 hours
  • Cost: use claude-haiku-4-5 for flat schemas with ≤10 fields — near-identical accuracy at a fraction of Sonnet's cost
  • Refusals: stop_reason: "refusal" can still occur; check before accessing .parsed_output
  • Both patterns compose: use output_format for Claude's answer AND strict: true on tools in the same agentic loop

Sources: Structured outputs — Claude Platform Docs · Strict tool use — Claude Platform Docs · Hands-on with Anthropic's structured output capabilities — Towards Data Science