- Home
- AI Handbook
- Practice
- Structured output: lists, tables, and JSON
[ Practice ]
Structured output: lists, tables, and JSON
Target audience: everyone | Prerequisites: 2.1 Getting to a good prompt
What you'll learn
After this document you will be able to:
- explain why free text suits a human but not the system that processes the result further;
- choose among three forms — the list, the table, and JSON — depending on who uses the answer;
- write a prompt (the instruction given to the model) so that the output format is explicitly required and the answers stay identical;
- fix the situation where the AI model deviates from the format — with a repetition rule, a strengthened example, and an automatic check.
In plain terms
When a human reads the answer, well-written text is enough. But when the answer must go on into a spreadsheet, a calculation, or another program, every data field needs a firm name and a firm place — then everyone knows where the price stands and where the floor area does. We call an answer in such a firm, machine-readable form structured output. This document teaches how to ask the model for such an answer — and what to do when the model breaks the rule.
Why free text doesn't work in a system
From document 1.5 you know that in an AI system the output is often the input of some other part. A human can manage to find the price inside a sentence; a program can't — every piece of information must have its place in order. Three problems that a free-text answer almost always causes in a system:
- The information is buried in the sentence. “An apartment in Karlova near the city center, 58 m², price 149 000 €, for sale immediately” — everything is there, but every value hides in a different spot. A program that is supposed to compute a price per square meter from the price doesn't know which number is the price and which is the floor area.
- A different wording every time. One day the model writes “three rooms”, the next “2 rooms and a kitchen”, the day after “3-room”. A human understands all three; for a spreadsheet, however, the system needs a value of the same shape, otherwise the columns aren't comparable.
- Extras nobody ordered. You ask for JSON and the model answers in good faith: “Of course! Here is the requested data:” — and only then come the data themselves. A human smiles; the program that expected JSON receives text that is wrong by its rules.
In plain terms: free text is the human language — we read and understand it. A system needs a place-for-everything record: every field named and in its fixed place, the same way every time.
The three forms: list, table, JSON
All three are structured outputs — the difference is in who they are meant for.
| Form | For whom | When it fits |
|---|---|---|
| List | human | Simple things: steps, a task list, where every line is one short item |
| Table | human | Comparing: several records and several attributes, the eye must scan the rows |
| JSON | machine | The answer goes on to a spreadsheet program or another system |
A list suffices when only one short field is needed from each record; but if a program must take over the answer, the safe choice is JSON.
JSON explained simply
JSON (a structured data format — key-value pairs) looks technical at first glance, but the principle is mundane: every piece of information is a pair in which one side says what the field is (the key) and the other what stands in it (the value). “price: 149000” is the JSON idea in its full extent.
{
"address": "12 Parnu Ave, Tartu",
"price_eur": 149000,
"area_m2": 58,
"rooms": 3,
"city": "Tartu"
}
Read it like one row of a table: the column heading on the left, the value on the right. The curly braces { and } hold the lines together into one whole — one record (for example, one apartment). When there are several records, they are placed between the square brackets [ and ] as a list. The brackets carry the structure: even if you can't program JSON yourself, every spreadsheet or calculation program knows that “price_eur” is always in the same place and means the same thing. That is why JSON is the form for handing data to a machine — the technical side of an output that crosses the system boundary is explained in 3.1.
In plain terms: JSON is like a form whose columns are written out in words. The key is the column heading, the value is the answer written into the box, and the brackets hold the rows together into one record.
How to demand a format in a prompt
A good format requirement consists of four parts:
- A precise description. Name every field and say what shape the value must have: “price_eur as an integer in euros, e.g. 149000”, “rooms as an integer; the kitchen does not count as a room”.
- One complete example of the expected output. Show the whole answer you expect — not “something like this” but a real record with real fields. The model imitates a shown pattern far more reliably than a long description (as 1.3 recommended as the fifth part).
- Rules for missing data. Always add: “If any data field is missing from the source, write an empty value — do NOT invent one.” Without it, the model fills the gaps by guessing, and the road to a hallucination (a confidently stated but wrong answer from the model) is short.
- Multi-state rules. State what must happen in different situations: “Answer with ONLY JSON, without introductory or closing text” and “if the task turns out to be unsolvable, answer in the form
{"error": "reason"}”.
And one more thing: write down the acceptance criterion — the condition under which the answer passes, for example “all 30 objects represented, exactly five fields in every record, not a single value added by the model itself”. This makes testing possible — how to develop a prompt in the test cycle is the topic of document 2.1.
In plain terms: demand the format the way a bank demands from a document: which page, which fields, what to do when something is missing — and don't enclose any extra pages either.
What to do when the model deviates from the format
Even with a proper prompt it happens: one record out of thirty stays half-finished or the model adds a courtesy phrase. Three steps, in order of importance:
- The repetition rule. The most common cause is that the format requirement stands in the middle of the prompt and slips out of attention (see 1.3's third most common mistake). Move the requirement to the beginning and repeat the critical part at the end: “Reminder: only JSON, no other text.”
- Strengthen the example. If the model still adds introductions, show the contrast in the example as well: “not like this: “Here is the data! { … }”, but exactly like this: { … }”. A good and a bad example side by side teaches faster than pleading.
- A check with an automatic rule. If a program processes the answer, let the program check it against a simple rule before use: is the answer even JSON, and are all the required fields present? If not — ask the model for a correction or send the record to a human. How to build such a check-and-repair cycle in a larger system is explained by 3.4 Errors and error handling.
Until the system has proven its reliability, the final approval stays with a human — this keeps a human in the loop (human-in-the-loop): the machine does, the human approves.
A step-by-step example: Annika's listing comparison table
Annika is a real estate broker. She has descriptions of 30 properties as free text (“an apartment in Karlova near the city center, 58 m², two rooms and a kitchen, price 149 000 € …”) and she wants to make a comparison table for a client out of them.
Step 1 — a free-form question, the result unusable.
Here are 30 real estate listings. Make a comparison from them.
The model writes a long, fluent summary: it mentions some prices, leaves some out, the order differs with every run, the room count sometimes in words, sometimes as a number. A human enjoys reading it; you can't paste it into a spreadsheet.
Step 2 — the format requirement.
Read the 30 real estate listings below and present one record per property
in the following JSON format (one list, 30 records):
[
{
"address": "12 Parnu Ave, Tartu",
"price_eur": 149000,
"area_m2": 58,
"rooms": 3,
"city": "Tartu"
}
]
Rules:
- price_eur: an integer in euros, only the price stated in the listing
- rooms: an integer; the kitchen and bathroom do not count as rooms
- There must be exactly 30 records, in the order of the listings.
- Answer with ONLY the JSON list, without introductory or
closing text.
Now all 30 records have the same construction — the columns land in place in the spreadsheet program.
Step 3 — the rule for missing data.
One listing doesn't mention the floor area. On the first run, the result said "area_m2": 55 — the model “helped” and guessed the area from the number of rooms. That is exactly a hallucination: a confident number found in no source. Annika adds one line to the rules:
- If any data field is missing from a listing, set its value to ""
(empty). Do NOT guess and do NOT fill in from general knowledge.
The new run gives "area_m2": "" for that property — and Annika sees exactly which record she must go back to her broker's data for. An empty value is honest; a guessed number would produce wrong conclusions later.
Step 4 — the final result in a table.
Because all the fields are always present and in the same order, reshaping the JSON into a table is simple — Annika pastes the answer into the spreadsheet program:
| address | price_eur | area_m2 | rooms | city |
|---|---|---|---|---|
| 12 Parnu Ave, Tartu | 149 000 | 58 | 3 | Tartu |
| 4 Kaubamaja St, Tartu | 210 000 | — | 4 | Tartu |
| 8 Rannahoone St, Parnu | 310 000 | 96 | 4 | Parnu |
We use the marker “—” to represent an empty value in the table.
The second row shows exactly what we wanted: the missing data field is visibly empty, not quietly guessed. If Annika wants to build a step further on this — the comparison is done, the next step composes a client letter from it — the next level is a workflow: how a structured output becomes the next step's input from one step's output is covered by 2.3.
Summary
- Free text is for a human, structure for a system. Information buried in the sentence, a different wording every time, and extras nobody ordered make a free-text answer unusable in a system.
- Three forms: the list for a simple rundown, the table for a human's comparing, JSON for handing data to a machine. JSON is a collection of key-value pairs whose structure the brackets hold.
- The format is demanded with four things: a precise description, one complete example, rules for missing data, and multi-state rules. The acceptance criterion says when the answer passes.
- A deviation is not a catastrophe: repeat the rule, strengthen the example, and have an automatic rule check it.
What's next?
- previous → 2.1 Getting to a good prompt
- next → 2.3 Basic workflows: steps and conditions
- The technical side of machine readability → 3.1 API integrations
- back → handbook index
Last updated 2026-10-05