Structured output as tables and JSON
From a markdown table to a strict JSON schema — how to specify columns and permitted values, why a fixed structure matters once output feeds a spreadsheet or a system, and what to do when the model wraps commentary around the JSON.
以繁體中文閱讀The problem: thirty sets of comments that will not line up
A Secondary 5 maths teacher ran first-pass assessment on her class's projects, one at a time, with this prompt:
Assess this project and give strengths and improvements in a table.
Thirty runs later she tried to merge the results into a spreadsheet and found the real problem. Some outputs had two columns (strengths, improvements), some had three (a score appeared), some rendered improvements as bullet points rather than cells, and five had a paragraph before the table saying "here is my assessment". The content was broadly fine, but merging meant two hours of manual alignment.
Same job, with the columns nailed down:
Role: you are an assessment assistant for Secondary 5 Mathematics projects.
Task: assess the project below and output a single table.
Output format: a markdown table with these columns in this order — student reference, clarity of inquiry question (1-5), data handling (1-5), soundness of conclusion (1-5), greatest strength (one sentence), priority improvement (one sentence), teacher verification needed (yes/no).
Constraints: output the table only, with no text before or after; do not add, remove or reorder columns; no cell longer than twenty words; scores must be whole numbers from 1 to 5. Do not rewrite the student's project. Where the project does not let you judge an item, leave the score blank and set teacher verification needed to "yes".
The second batch of thirty went straight into the spreadsheet with no handwork at all.
Why this works
Every generation is a fresh decision about how best to present something. Give no format and the model improvises from the content — a virtue when writing prose, a disaster when merging data. Structured output moves presentation from the model's discretion into your specification.
Picture asking thirty colleagues each for a lesson observation record. Say "write a record" and you get thirty formats; hand out a printed form with the fields already on it and you get thirty records you can tabulate. The form's value is not tidiness. It is that it makes the thirty-first step possible.
One thing gets overlooked: fixed fields are also a safety design. Requiring a "teacher verification needed" column gives the model somewhere to be honest when it is unsure, instead of inventing a number to fill the row — the same logic as authorising "not found" in grounded prompts with citations.
JSON is the version written for machines. It is stricter than a table: field names, data types and permitted values all have to be settled in advance. The good news is that the major providers now offer structured output modes where the API guarantees conformance to a schema rather than leaving it to luck in the prompt. Any school building an integration needs that layer. Teachers working in a chat interface can get most of the way with a prompt plus one worked example.
Template 1: a markdown table for people
Role: you are a batch collation assistant for a [subject] teacher.
Task: organise the [student responses / observation notes / survey answers] below into one table.
Output format: a single markdown table with these columns in this order — item number, summary of the original (twenty words maximum), category, severity (high/medium/low), suggested follow-up, teacher verification needed (yes/no).
Constraints: output the table only, with no text or heading before or after; do not add, rename or reorder columns; "category" may take only one of these values — conceptual understanding, calculation technique, reading the question, expression, other. Where you cannot judge, set category to "other" and teacher verification needed to "yes" rather than guessing. Do not rewrite the original content; summaries must stay faithful to the original sentences.
Data:
[paste content]
Template 2: strict JSON for a system
Role: you are a marking service that emits JSON and does not converse.
Task: mark the student response below against the rubric and output one JSON object.
Output format: output exactly one JSON object with this structure, with field names and casing matching exactly:
{
"student_ref": "string, the reference the teacher supplied",
"criteria": [
{ "name": "string", "score": integer 1-5, "evidence": "string, one sentence quoted from the student response", "comment": "string, 40 words maximum" }
],
"total": integer,
"needs_teacher_review": true or false,
"review_reason": "string, or \"none\" when needs_teacher_review is false"
}
Constraints: output JSON only, with no text, heading or explanation before or after, and no comments inside it. Do not add or omit fields — use the agreed empty value rather than dropping a field. Scores must be whole numbers from 1 to 5, never decimals or words. Evidence must be a sentence from the student's own text, neither rewritten nor translated. Whenever the evidence is too thin to judge, set needs_teacher_review to true and explain in review_reason. Do not rewrite the student's response.
Rubric: [paste rubric]
Student response: [paste response]
Template 3: when the same data needs both formats
Ask for JSON first, then build the table from it, and the two cannot disagree.
Role: you are a format conversion assistant.
Task: convert the JSON below into a markdown table for a teachers' meeting, changing no values.
Output format: a single markdown table, one row per criteria item, with these columns in this order — criterion, score, key evidence, comment, teacher review. Add one total row beneath the table.
Constraints: output the table only. Every value must match the JSON exactly, with no rounding, conversion or addition. Anything absent from the JSON stays blank and must never be inferred. Where needs_teacher_review is true, put "yes" in the teacher review column and carry over the review_reason text.
JSON:
[paste JSON]
Handling commentary wrapped around the JSON
Even with "output JSON only" in the prompt, an opening line still slips through. Three fixes, easiest first:
- Supply one complete worked example. An example does far more than a description, especially written as a whole object rather than field-by-field notes.
- List the prohibitions explicitly. "No opening line, no closing line, no heading, no explanation, nothing outside the object" — itemised, this is far more reliable than a single "JSON only".
- Switch to the provider's structured output mode. OpenAI and Google both offer schema-constrained responses where the API enforces the format. Any school wiring AI output into a school system needs this layer, because a prompt always carries a failure rate.
Common mistakes
- Writing only "present this as a table". Columns differ every run and merging becomes manual. Fix: list the column names and order, and forbid additions and removals.
- Not constraining permitted values. The category column reads "unclear concept" on one run and "conceptual understanding issue" on the next, so statistics see two categories. Fix: give a closed list of permitted values and a fixed "other" for anything that will not fit.
- Dropping a field when there is no value. One missing JSON field and the downstream code breaks. Fix: require an agreed empty string or null, keeping the structure complete.
- No verification column, so the model invents to fill the row. This is the counter-intuitive risk of structured output: the tidier the format, the harder errors are to see. Fix: always carry a "teacher verification needed" field and say in the constraints exactly when it must be set.
Going further
- Science experiment data: add a units column and a column recording whether a value came from the student's own measurements or was derived by the AI. Without it, derived values get read as measured ones.
- Chinese Language character error tracking: change the columns to original sentence, incorrect character, correct form, error type (similar shape / similar sound / other), and frequency. Merged across a whole Secondary 3 cohort, it shows the panel which error types to target this year.
- General Studies survey collation: before classifying open responses, have the AI propose ten categories in one pass, let the teacher edit them into a closed list, then run template 1 across the batch. Defining categories before classifying gives far steadier results.
- Comparing sources in Citizenship and Social Development: add a stance column with permitted values of supports, opposes, neutral and cannot tell, and forbid guessing when it is the last of those.
- Observation records for students with SEN: use observable behaviour, context, support provided and outcome (improved / unchanged / worse / cannot tell). Keep names out of the records and use references instead, for the reasons set out in school administration and parent communication prompts.
Where to go next
Structured output is the step that takes AI from "write me a paragraph" to "process these thirty". The tighter the specification, the easier merging and analysis become — and an honest verification column is the one design that stops a tidy format from hiding errors.
The same field discipline applied to images, handwritten work and speech is in multimodal prompts. Keeping the specifications you settle on as a shared asset is covered in building a panel prompt template library.
Key takeaways
- A usable table needs every column named, ordered and value-constrained; "present this as a table" produces different columns every time.
- The value of a fixed structure lies in the step after — when thirty outputs are merged, drifting columns are harder to repair than wrong content.
- For JSON, spell out the sole-output rule — no commentary, nothing outside the object, and a defined empty value rather than a dropped field.
- Any column holding facts or scores needs a verification column so the model can flag uncertainty instead of inventing something to fill the row.
FAQ
Because you did not specify them. With no column spec the model improvises from the content — three columns today, five tomorrow — and merging becomes manual. Write out the column names and their order, add a constraint forbidding any addition or removal, and require a fixed placeholder string for empty cells rather than dropping a column.
Do two things together. In the prompt, state that JSON is the only output with no text before or after, and supply one complete example object. At the system level, use the provider's structured output or JSON mode, where the API guarantees the response conforms to the schema you supply. Both together bring the failure rate down to where automation is safe.
By who handles it next. A markdown table suits anything a person reads, pastes into a document or copies into a spreadsheet. JSON suits anything read by code, imported into a system, or kept for long-term statistics. When the same data needs both, ask for JSON first and then have the model build the table from that JSON, which guarantees the two agree.
- · All prices, features and specifications follow the official documentation linked above. Vendors may change them at any time — verify before you purchase.
- · Product names and trademarks mentioned belong to their respective owners. Edor.ai has no partnership, agency or sponsorship relationship with these companies.
- · This article is an independent review compiled for educational purposes and is not procurement advice or legal advice.
- · For any use involving student personal data, assess it against your school policy and the Personal Data (Privacy) Ordinance (PDPO) before rollout.