Structured Output Prompting: Get JSON, Tables and Code from Any LLM
Learn structured output prompting to extract JSON, Markdown tables, and code from LLMs reliably. Includes schema design, validation patterns, and real examples.
Get more content like this on Telegram!
Daily AI tips, notes & resources β free
The first time I tried to pipe an LLM response into a database, I got back a beautifully written paragraph explaining the data I'd asked for. Useless. I needed a JSON object with specific fields. What I got was prose.
That gap β between what LLMs naturally produce and what applications need to consume β is where structured output prompting lives. It's not glamorous. It's not the flashiest area of prompt engineering. But for anyone building anything real with LLMs, it's arguably the most practically important skill.
This guide covers how to get consistent, parseable, production-ready output from any major LLM.
Why Unstructured Output Breaks Pipelines
A language model's natural output format is continuous prose. That's what it was trained on. When you ask for "a list of the top 5 programming languages," you might get:
- A numbered list with headers
- A paragraph with inline mentions
- A table
- A bulleted list with or without descriptions
- Some combination of all of the above
Every generation is slightly different. Any code that tries to parse that consistently will break regularly.
Structured output prompting is about giving the model a format specification tight enough that it produces reliably parseable output, every time.
JSON Output: The Foundation
JSON is the most common structured output format because it maps directly to how most applications handle data. Here's how to prompt for it reliably.
The minimal working JSON prompt:
Extract the following information from the text below and return it
as a valid JSON object. Return ONLY the JSON β no explanation,
no markdown code block, no additional text.
Schema:
{
"name": "string",
"email": "string",
"company": "string",
"request_type": "string (one of: sales, support, demo, other)"
}
Text to process:
[paste your text]
That's the baseline. Three elements: explicit format instruction, a clear schema, and the data. This works reliably for simple flat structures.
For more complex schemas, include an example:
Extract product information from the review below and return it as
valid JSON matching this schema exactly. Return ONLY the JSON object.
Schema with example values:
{
"product_name": "Example Widget Pro",
"rating": 4,
"sentiment": "positive",
"mentioned_features": ["feature1", "feature2"],
"would_recommend": true,
"main_complaint": "string or null if no complaint mentioned"
}
Important:
- rating must be an integer 1-5
- sentiment must be exactly "positive", "negative", or "mixed"
- would_recommend must be a boolean
- mentioned_features must be an array (empty array if none mentioned)
- main_complaint must be null if not applicable
Review text:
[paste review]
The "Important" section is where most prompts fall short. LLMs need explicit constraints on data types, allowed values, and nullable fields β otherwise they make reasonable-but-wrong choices like returning "4/5" for a rating or "N/A" instead of null.
Arrays and Collections
Prompting for arrays of objects is where format consistency starts getting fragile. Small changes in phrasing produce very different structures.
Array output prompt pattern:
Analyze the following text and extract all mentioned people as a
JSON array. Each person should be an object in the array.
Return ONLY a valid JSON array β no other text or explanation.
Schema for each person object:
{
"name": "string (full name as mentioned)",
"role": "string or null if not mentioned",
"organization": "string or null if not mentioned",
"sentiment_toward_them": "positive | negative | neutral"
}
If no people are mentioned, return an empty array: []
Text:
[paste text]
Two things to note: the empty array fallback is important (LLMs sometimes return null or an explanation instead of [] when nothing matches), and the | notation for enum values is cleaner than writing "must be one of" in prose.
Nested arrays β the tricky case:
Extract the following data structure from the sales report below.
Return ONLY valid JSON matching this exact structure:
{
"report_period": "string (e.g., Q1 2026)",
"regions": [
{
"region_name": "string",
"total_revenue": "number (in USD, no currency symbol)",
"products": [
{
"product_id": "string",
"units_sold": "integer",
"revenue": "number"
}
]
}
],
"total_company_revenue": "number"
}
Include all regions and products mentioned.
If a numeric value is not mentioned, use 0.
Report text:
[paste report]
For deep nesting like this, the example structure itself does most of the work. Prose descriptions of nested arrays are almost always misinterpreted.
Markdown Tables
Sometimes JSON isn't what you need. For display in documentation, reports, or content generation, Markdown tables are more directly useful.
The table prompt pattern:
Create a comparison table of the following items using Markdown table syntax.
Items to compare: [list your items]
Comparison dimensions: [list the dimensions/columns]
Format requirements:
- Use proper Markdown table syntax with header row and separator row
- Align numeric columns to the right using :---: or ---:
- Keep cell content concise (under 15 words per cell)
- Use "β" for any data that is not applicable or unknown
- Return ONLY the Markdown table, no introduction or explanation
Practical example β comparing LLM API pricing:
Create a Markdown comparison table for these LLM APIs.
Models to include: GPT-4o, Claude 3.5 Sonnet, Gemini 1.5 Pro,
Llama 3.1 70B (via Groq)
Columns: Model, Provider, Input cost per 1M tokens, Output cost
per 1M tokens, Context window, JSON mode support, Best use case
Use current publicly available pricing. Use "β" where unknown.
Return ONLY the Markdown table.
This produces directly embeddable Markdown. Useful for documentation pipelines, content generation, and any workflow where tables need to be generated programmatically.
Code Generation with Structured Constraints
Code output is a special case of structured output β the structure is the syntax of the target language. Getting consistent, usable code means being explicit about more than just "write Python code."
The code output specification pattern:
Write a Python function that [description of what it should do].
Technical requirements:
- Function signature: def process_items(items: list[dict]) -> list[dict]
- Input: list of dictionaries, each with keys: "id" (str), "value" (float), "active" (bool)
- Output: filtered and transformed list (same structure)
- Handle edge cases: empty list, None values in "value" field, missing keys
- Include type hints throughout
- Add a docstring with: description, Args, Returns, Raises sections
- No external dependencies beyond Python standard library
Return ONLY the function code, no explanation, no usage example,
no imports beyond what the function itself needs.
Compare that to "write a Python function to process items" β the structured specification produces code you can actually drop into a codebase without editing.
For more complex code with multiple components:
Generate a FastAPI endpoint with the following specification:
Endpoint: POST /api/v1/process-text
Request body schema (JSON):
{
"text": "string (required, max 5000 chars)",
"language": "string (optional, default: 'en', ISO 639-1 code)",
"options": {
"summarize": "boolean (optional, default: false)",
"extract_keywords": "boolean (optional, default: false)"
}
}
Response schema (JSON):
{
"request_id": "string (UUID)",
"processed_text": "string",
"keywords": "array of strings (empty if extract_keywords is false)",
"summary": "string or null (null if summarize is false)",
"processing_time_ms": "integer"
}
Include:
- Pydantic models for request and response
- Input validation with descriptive error messages
- Proper HTTP status codes (200, 400, 422)
- Type hints throughout
Return ONLY the Python code, no explanation.
This approach is the foundation of what most production LLM integrations do. If you're building with the Claude or OpenAI APIs, you'll recognize this pattern β check out our prompt engineering course for how these techniques connect to production system design.
LLM Comparison: Structured Output Reliability
| Model | JSON Reliability | Schema Adherence | Nested Structures | JSON Mode Available |
|---|---|---|---|---|
| GPT-4o (API) | Excellent | Excellent | Good | Yes (API param) |
| Claude 3.5 Sonnet | Excellent | Excellent | Excellent | No, but consistent |
| Gemini 1.5 Pro | Good | Good | Moderate | Yes (API param) |
| GPT-4o mini | Good | Good | Moderate | Yes (API param) |
| Llama 3.1 70B | Moderate | Moderate | Limited | With Outlines lib |
| Mistral Large | Good | Good | Moderate | No |
Claude's performance on nested structures is notably strong β it tends to follow complex schemas more faithfully than GPT-4o, possibly because Anthropic's training specifically emphasizes instruction following. For simpler flat structures, any frontier model is reliable.
For production systems, use API-level JSON mode when it's available. Prompt-based JSON is good for experimentation and less-critical pipelines.
CSV and Tabular Data Output
For data workflows that need CSV output directly:
Convert the following information into CSV format.
Requirements:
- First row must be headers
- Use comma delimiter
- Wrap any field containing commas or newlines in double quotes
- Use "null" (without quotes) for missing values
- Dates in ISO 8601 format (YYYY-MM-DD)
- No spaces after commas
- Return ONLY the CSV data, no explanation
Columns: id, name, date, value, category, notes
Data to convert:
[paste your data]
Handling Ambiguous and Missing Data
The hardest structured output problems involve partial information β what should the model put in a field when the source data doesn't clearly answer the question?
The explicit uncertainty pattern:
Extract the following fields from the text. For each field, if the
information is:
- Clearly stated: extract the exact value
- Implied but not stated: extract with confidence "inferred"
- Not mentioned at all: use null
Return as JSON:
{
"company_size": {
"value": "string or null",
"confidence": "explicit | inferred | null"
},
"funding_stage": {
"value": "string or null",
"confidence": "explicit | inferred | null"
},
"headquarters_city": {
"value": "string or null",
"confidence": "explicit | inferred | null"
}
}
This pattern is useful for data extraction from unstructured sources where you need to distinguish between confirmed facts and reasonable inferences. It's a significant step up from asking for a flat JSON extraction and getting confidently wrong values for fields that weren't actually mentioned.
Validation and Error Handling in Prompts
Build validation instructions directly into your prompts:
After generating the JSON object, before returning it:
1. Verify all required fields are present (name, email, status)
2. Verify status is exactly one of: "active", "inactive", "pending"
3. Verify email contains "@" and "."
4. Verify any numeric fields contain only numbers, not strings
If any validation fails, fix the issue in the JSON before returning.
Return ONLY the validated JSON object.
This self-validation step catches a significant proportion of format errors before they reach your parsing code. It's not a substitute for code-level validation, but it reduces the failure rate substantially.
The chain of thought prompting guide covers a related technique β asking models to reason before outputting β that pairs well with structured output when you need both accurate values and consistent format.
Production Patterns: Beyond Prompting
For high-volume or critical production use, prompt-only structured output isn't enough. Three tools worth knowing:
Instructor (Python): Wraps the OpenAI and Anthropic APIs with Pydantic model validation. Define your output as a Pydantic class, and Instructor automatically retries with corrective feedback when the model produces invalid output.
import instructor
from anthropic import Anthropic
from pydantic import BaseModel
class ProductReview(BaseModel):
product_name: str
rating: int # 1-5
sentiment: str # positive, negative, mixed
would_recommend: bool
client = instructor.from_anthropic(Anthropic())
review = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[{
"role": "user",
"content": f"Extract product review data from: {review_text}"
}],
response_model=ProductReview,
)
Outlines: For open-source models, Outlines constrains token generation to match your schema at the decoding level. The model literally cannot produce invalid JSON because invalid tokens are blocked during generation.
OpenAI JSON mode: Pass response_format={"type": "json_object"} to the API. The model is guaranteed to return valid JSON (though not necessarily matching your specific schema β you still need to prompt for the right structure).
For developers working through the JavaScript/React course or learning TypeScript, these API integration patterns connect directly to what you'll build in frontend and full-stack work. The TypeScript cheatsheet covers how to type LLM response objects once you have consistent structured output flowing from your prompts.
π¬ DiscussionPowered by GitHub Discussions
Frequently Asked Questions
AiTechWorlds Team
β Verified WriterThe AiTechWorlds team is passionate about AI, technology, and education. We create high-quality, research-backed content to help you learn, grow, and succeed in the modern digital world.
Related Articles
Chain-of-Thought Prompting: The Complete Guide to Step-by-Step AI Reasoning
Master chain-of-thought prompting to unlock step-by-step AI reasoning. Real examples, benchmarks, and techniques that actually improve LLM accuracy.
100 Best ChatGPT Prompts for Productivity and Work (2026)
100 best ChatGPT prompts for productivity in 2026. Cut meeting prep, email, and planning time in half with prompts that actually work at the office.
Role Prompting: How to Set AI Context for Better, Smarter Outputs
Role prompting techniques that actually work: how assigning AI personas shapes reasoning, tone, and accuracy across writing, coding, and analysis tasks.
System Prompt Engineering: Writing Effective AI Instructions That Work
System prompt engineering guide with real examples, proven patterns, and practical techniques for building AI assistants that behave consistently and reliably.