Skip to content
Tools

How to Fix Broken JSON from ChatGPT and Other LLMs

· 4 min read

LLM output usually breaks JSON in predictable ways: it is wrapped in Markdown code fences, surrounded by explanation, cut off by the token limit, or contains JavaScript-style syntax such as trailing commas and single quotes. Paste it into the LLM JSON fixer to extract and repair it, and in your code prevent the problem with schema-constrained output plus validation.

Language models generate text one token at a time, and nothing forces that text to be valid JSON unless the API constrains it. Below are the failure modes, how to repair each one, and how to stop them in production.

The six common failure modes

SymptomExampleFix
Markdown code fenceOutput starts with three backticks and jsonStrip everything before the first { or [ and after the matching close.
Prose around the JSON"Sure! Here is the data: {...} Let me know if..."Same: extract the outermost object or array.
Truncated outputEnds mid-string: {"items": [{"name": "AlRaise the output token limit or ask for fewer items. Repairing by closing brackets loses data.
JavaScript syntaxTrailing commas, 'single quotes', unquoted keys, // commentsRepair automatically, or parse as JSON5.
Smart quotes“name”: “Ada”Replace curly quotes used as delimiters with straight double quotes.
Invalid valuesNaN, undefined, None, TrueMap to null, true, false.

Repairing a one-off response

For output you are reading by hand, paste it into Fix LLM JSON. It strips fences and surrounding text, repairs the syntax issues above, and shows a diff of every change so nothing is silently rewritten. It runs in your browser, which matters if the response contains customer data or keys. For JSON that is broken for other reasons (hand-edited configs, logs), the general JSON fixer does the same repairs without the LLM-specific extraction.

Extracting JSON in code

A small extraction step handles fences and prose without regex gymnastics: find the first opening bracket, the last matching closing bracket, and parse what is between them.

function extractJson(text) {
  const start = text.search(/[[{]/);
  if (start === -1) throw new Error("No JSON found in model output");
  const close = text[start] === "{" ? "}" : "]";
  const end = text.lastIndexOf(close);
  if (end <= start) throw new Error("Model output looks truncated");
  return JSON.parse(text.slice(start, end + 1));
}

This fails loudly when the output is truncated, which is what you want: a truncated list that has been "repaired" by closing the brackets looks valid but is missing data. Catch the error and retry with a larger token limit or a smaller request.

Prevent it: ask the API for structured output

Prompting "respond only with JSON" helps but is not a guarantee. Major model APIs offer stronger options; check your provider's current documentation for exact parameter names and supported models:

  • JSON mode: the API guarantees syntactically valid JSON, but not that it matches your fields.
  • Schema-constrained output (structured outputs): you pass a JSON Schema and decoding is constrained so the response matches it. OpenAI and Google Gemini both document this, and other providers offer equivalents.
  • Tool or function calling: you define a tool with a JSON Schema for its arguments and the model returns arguments as JSON. Anthropic's Claude API supports this pattern.

Even with these, keep a validation step. Schema support varies (some keywords are not supported in constrained modes), responses can still be cut off by the token limit, and a valid structure can still contain wrong values.

Validate every response

Parsing proves the text is JSON. Validation proves it is the JSON you expected. In TypeScript, Zod gives you a runtime check and a static type from one definition:

import { z } from "zod";

const Product = z.object({
  name: z.string(),
  price: z.number().nonnegative(),
  tags: z.array(z.string()).default([]),
});

const result = Product.safeParse(extractJson(modelText));
if (!result.success) {
  // Send result.error.issues back to the model in a retry, or log and fail
  throw new Error(result.error.message);
}
const product = result.data; // typed as { name: string; price: number; tags: string[] }

In Python, Pydantic does the same with Product.model_validate_json(text). You can generate a starter Zod schema from a sample response with the JSON to Zod converter, or a JSON Schema with the schema generator and test responses against it in the schema validator.

Prompting tips that reduce breakage

  • Include a short example of the exact output shape, with the real key names.
  • Say what to do with unknown values ("use null") so the model does not invent N/A strings or omit keys.
  • Ask for fewer items per call. Long lists are where truncation happens.
  • Set temperature low for extraction tasks.
  • On a validation failure, retry once with the error message included; repeated retries rarely help.

If a model keeps returning JSON with comments or trailing commas, it may be imitating config files. JSON vs JSON5 vs JSONC explains the difference, and common JSON errors covers the rest of the syntax rules.

FAQ

Why does ChatGPT return invalid JSON?

Without a schema or JSON mode, the model generates free text that only resembles JSON. It may add code fences, explanations, trailing commas or stop at the token limit mid-object.

How do I extract JSON from text?

Take the substring from the first { or [ to the last matching } or ] and parse it, or paste the text into Fix LLM JSON, which does this and repairs common syntax errors.

Can truncated JSON be fixed?

It can be made syntactically valid by closing open strings and brackets, but the missing data is gone. Increase the output token limit or request smaller batches instead.

Does JSON mode guarantee my schema?

No. JSON mode guarantees valid syntax only. Use schema-constrained structured output where available, and validate the result in your code.

Is it safe to paste model output into an online fixer?

Only if the tool runs locally. Our LLM JSON fixer processes everything in your browser and does not upload the text.

More JSON guides