Getting structured output: tables, JSON and checklists
Learn to ask for answers in a fixed shape (tables, checklists and JSON) so you can scan them quickly, paste them into other tools or read them in code. You'll also see how to check and repair JSON that comes back.
By default an AI replies in flowing paragraphs. That is fine for a chat, but not when you want to compare options, paste results into a spreadsheet or read the answer in a program. For that you ask for a structure: a table, a checklist or JSON.
In this tutorial you will turn the same Brew & Bean order message into a table, a checklist and a JSON object, then read the JSON with a short Python script. You need a free chat tool (ChatGPT, Gemini, Claude or Copilot). Python 3 is needed only for the last part. You should have read *Anatomy of a good prompt*: format is one of its six parts.
Tables: for comparing things
How to ask for any structure
- 1Say what the output is for (reading, ticking off, pasting into Excel, or a program).
- 2Describe the exact shape: column names, checklist groups or JSON keys and types.
- 3Say what to do when information is missing.
- 4Ask for the structure only, with no extra chat text if a program will read it.
- 5Check the result, and for JSON validate it in code.
Tables work best when you have several items and the same few questions about each. Name the columns yourself, in order. If you don't, the model picks columns for you, and they change from run to run.
Compare Python, Java and JavaScript for a first-year B.Tech student who wants to get a campus placement.
Format: a table with exactly these columns: Language | Easy to learn (1-5) | Used for | Placement relevance (one sentence).
One row per language. After the table, add one line recommending a starting language and why. No other text.What to expect: You should get a clean table with three rows and four columns, then one recommendation line. Scores are opinions, so treat them as a starting point, not data.
Most chat tools show a table as a grid. If you want to paste it into a spreadsheet, add: "Give the table in CSV format inside a code block." CSV is plain text with commas between columns, which Excel and Google Sheets can import.
Checklists: for things you will do
Brew & Bean is a pickup-only coffee shop open 8 am to 10 pm. Write the closing checklist for the person who closes the shop at 10 pm.
Format: a checklist of 10-12 items. Each item starts with a verb and can be ticked off in under 5 minutes. Group the items under three headings: Counter, Kitchen, Cash and orders. Do not add explanations.What to expect: Check that every item is a single action you can tick off ("Wipe the espresso machine steam wand"), not a vague goal ("Make sure everything is clean").
Say what the items look like
"Each item starts with a verb and takes under 5 minutes" is what turns a vague list into a usable checklist. Without it you often get a mix of actions, advice and reminders.
JSON: for programs
JSON is a text format that programs can read. An object is written in curly braces with "key": value pairs. Text values are in double quotes, numbers are not, and lists are in square brackets. Almost every language can parse it.
Below is a real message a customer might send to the shop. Our goal is to turn it into an order object matching the Brew & Bean order shape: customer_name, items (each with item_id and qty) and pickup_time.
Extract an order from the customer message below.
Return ONLY a JSON object, with no explanation and no code fences, in exactly this shape:
{"customer_name": string or null, "items": [{"item_id": string, "qty": integer}], "pickup_time": string or null}
Rules:
- item_id must be one of: espresso, cappuccino, cold-brew, filter-coffee, masala-chai, croissant, banana-bread, veg-sandwich.
- If a value is not in the message, use null. Do not guess.
- pickup_time stays as the customer wrote it.
Message:
---
Hi, this is Divya. 2 cappuccinos and one banana bread please, I'll pick up around 6:30 in the evening.
---What to expect: Expected: {"customer_name": "Divya", "items": [{"item_id": "cappuccino", "qty": 2}, {"item_id": "banana-bread", "qty": 1}], "pickup_time": "around 6:30 in the evening"}. Notice there is no phone number in the message, and the shape had no phone field, so nothing is invented.
What makes a JSON request work
Five habits for reliable JSON
| Habit | Why | Example wording |
|---|---|---|
| Show the exact shape | The model copies key names and nesting | Paste a sample object with the types |
| Fix the allowed values | Stops invented categories | "item_id must be one of: ..." |
| Say what to do when data is missing | Stops guessing | "Use null. Do not guess." |
| Ask for JSON only | Extra chat text breaks parsers | "No explanation, no code fences" |
| Add one example | Shows edge cases like empty lists | Few-shot, see *Zero-shot and few-shot* |
Valid shape is not the same as true content
The model can return perfectly formatted JSON with a wrong value, for example the wrong quantity. Always validate in code (types, allowed values, ranges) and, for anything important such as prices and totals, calculate them yourself. In Brew & Bean the server computes total from the menu; never trust a total the model wrote.
Read the JSON in Python
Copy the model's JSON reply into a file called reply.json (just the JSON). Then save the script below as read_order.py in the same folder and run python read_order.py. It parses the text and checks it, which is what any program using an AI reply should do. Models sometimes wrap JSON in code fences even when told not to, so the script strips them.
import json
VALID_ITEMS = {
"espresso", "cappuccino", "cold-brew", "filter-coffee",
"masala-chai", "croissant", "banana-bread", "veg-sandwich",
}
def clean(text):
"""Remove ``` fences if the model added them."""
text = text.strip()
if text.startswith("```"):
lines = text.splitlines()[1:]
if lines and lines[-1].strip().startswith("```"):
lines = lines[:-1]
text = "\n".join(lines)
return text.strip()
def parse_order(text):
order = json.loads(clean(text))
if not isinstance(order.get("items"), list) or not order["items"]:
raise ValueError("items must be a non-empty list")
for item in order["items"]:
if item.get("item_id") not in VALID_ITEMS:
raise ValueError(f"unknown item_id: {item.get('item_id')}")
qty = item.get("qty")
if not isinstance(qty, int) or qty < 1:
raise ValueError(f"bad qty for {item['item_id']}: {qty}")
return order
with open("reply.json", encoding="utf-8") as f:
reply = f.read()
try:
order = parse_order(reply)
print("Order OK for", order.get("customer_name") or "unknown customer")
for item in order["items"]:
print(f" {item['qty']} x {item['item_id']}")
print("Pickup:", order.get("pickup_time") or "not given")
except (json.JSONDecodeError, ValueError) as err:
print("Problem with the reply:", err)json.loads turns the text into Python dicts and lists. The checks after it reject anything that is not a real menu item or a positive whole number.
Order OK for Divya
2 x cappuccino
1 x banana-bread
Pickup: around 6:30 in the eveningIf the script prints Problem with the reply, you have found the reason programs need checks. Paste the error and the reply back to the model and ask it to fix the JSON (next prompt). APIs from some providers can also enforce a JSON schema for you; that is covered later in *Structured output with JSON schemas* in the AI Engineering track.
The JSON below failed to parse with this error: [paste error message].
Fix it so it is valid JSON. Do not change any values. Return only the corrected JSON.
---
[paste the JSON]
---What to expect: Typical causes: a trailing comma, single quotes instead of double quotes, or text before or after the object. The fixed version should differ only in punctuation.
Choosing the right format
Which structure when
| You want to... | Ask for |
|---|---|
| Compare several things on the same points | A table with named columns |
| Do something step by step or check things off | A numbered list or checklist |
| Paste into Excel or Google Sheets | CSV in a code block |
| Read the answer in your own code | JSON with a fixed shape |
| Read quickly on a phone | Short bullets; avoid wide tables |
Try it: Structure your own data
Paste three real messages from your life (a college WhatsApp group notice, a friend's trip plan, a job alert email). For each, ask for JSON with fields you choose, for example event, date, venue, deadline. Use null for missing values. Then write a 10-line Python script that loads the JSON and prints it nicely.
Key takeaways
- Name the structure and its parts: table columns, checklist grouping, JSON keys and types.
- Tables compare, checklists guide action, JSON feeds programs, CSV feeds spreadsheets.
- For JSON: show the exact shape, limit allowed values, say what to do with missing data and ask for JSON only.
- Always parse and validate JSON in code; valid format does not mean correct content.
- When JSON breaks, send the error and the text back and ask for a fix that changes no values.
Check yourself
Finishing the quiz marks the lesson as done.
1. You ask for JSON and the customer's phone number is not in the message. What should your prompt tell the model to do?
2. Why should the prompt say "no explanation, no code fences" when you want JSON for a program?
3. The model returns valid JSON with qty 20 for a message that said "2 cappuccinos". What does this show?
4. You want to compare four laptops on price, RAM and battery in a way that is easy to scan. Which request is best?
5. What is the best way to stop the model from inventing an item_id that is not on your menu?
Saved on this device. Create a free account to keep it on every device.
Practise this with Sam
A real mock interview, out loud, with an honest scorecard. Free to start.