Ashvara
Blog/Engineering
Engineering

Getting reliable JSON out of an LLM (stop parsing hope)

Prompting for JSON fails 5-10% of the time; schema-enforced structured output is ~100% valid via constrained decoding. Use it, and still validate in code.

S
Sahil Jain
Engineering · Ashvara
Jul 23, 2026
6 min read
Structured output

If your app depends on an LLM returning JSON, don't ask it nicely and parse the result with a regex - use schema-enforced structured output, which is essentially 100% valid because the model is constrained to your schema at generation time. Asking a model to "please return JSON" fails somewhere between 5% and 10% of the time, and those failures show up as production incidents at 2am, not in your demo. The good news is that reliable JSON is a solved problem in 2026: the major providers can constrain generation to a JSON Schema you supply, so the output can't come out malformed. The engineering job is to use that capability - and still validate the parsed object in code, because "valid JSON" and "the data you actually needed" aren't the same thing.

Why this matters now

The moment an LLM's output feeds another system - a database write, an API call, a UI render - loose JSON becomes a reliability problem. A 5% parse-failure rate is invisible in testing and catastrophic at scale: at a thousand requests a day, that's fifty broken responses. Teams that treated this as "the model is flaky" were usually just using the weakest extraction method.

There's a clear reliability ladder, and it's worth knowing exactly where each rung lands.

Diagram of four ways to get JSON from an LLM: rung 1, please-return-JSON in the prompt with hope and regex parsing, about 80 to 95 percent valid and zero added latency; rung 2, JSON mode, valid JSON but not necessarily your shape, about 95 to 99 percent and roughly 50ms; rung 3, structured output with schema enforcement via constrained decoding, about 100 percent valid and roughly 100ms; rung 4, adding validate-and-retry on a schema failure for near-zero failure at 200 to 500ms per retry; a panel explaining that constrained decoding runs a finite-state machine over your schema and masks any token that would make the output invalid so the model literally can't emit the wrong shape, with a note that provider support varies; and a rule to use schema-enforced structured output and still validate the parsed object against your schema in code

The four rungs, and where to stand

  • "Please return JSON" in the prompt (~80-95% valid, +0ms). The default, and the trap. It works most of the time, which is exactly what makes the 5-20% of failures so easy to ship. Regex-parsing model output is a code smell.
  • JSON mode (~95-99%, +~50ms). The model is constrained to emit syntactically valid JSON - but not necessarily your schema. Better, still not a guarantee that the fields you need are present and correctly typed.
  • Structured output, schema-enforced (~100% valid, +~100ms). You pass an actual JSON Schema and the provider uses constrained decoding to guarantee the response matches it - right field names, right types, all required properties. This is the rung to stand on for production.
  • Add validate-and-retry (~0% failure, +200-500ms per retry). Wrap the call so a schema-validation failure re-asks the model. Belt and braces for the highest-stakes paths.

The mechanism: the model can't emit the wrong shape

This is the part worth understanding, because it explains why rung 3 is a guarantee and not just "better."

Constrained decoding runs a finite-state machine derived from your schema alongside generation. At every token, it computes which next tokens would keep the output valid against the schema and masks out all the others - the model is only allowed to sample from the legal set. It's not being asked to try to produce valid JSON; it's structurally prevented from producing anything else. Types and required fields are enforced at generation time, not checked afterward.

The difference between "the model usually returns valid JSON" and "the model cannot return invalid JSON" isn't a percentage - it's the difference between a data pipeline that occasionally corrupts and one that can't. Constrained decoding buys you the second one.

One important caveat: support and strictness vary by provider. Some guarantee the schema via constrained decoding; others accept a schema but only make a best effort to honor it. If your provider is best-effort, you're really on rung 2 with extra steps, and the validate-and-retry wrapper matters more. Check what your model actually promises before you rely on it. (Self-hosting? Constrained-decoding engines bolt onto the popular inference servers and enforce the grammar for you.)

What to actually do

  • Default to schema-enforced structured output for anything downstream of the model. Define the schema, pass it, let constrained decoding do the work.
  • Still validate the parsed object in code against the same schema. Structured output guarantees shape, not sense - a field can be present, correctly typed, and semantically wrong. Validation at the boundary is cheap insurance.
  • Add retry on the paths that can't fail. For a write that moves money or state, the extra 200-500ms of a retry is nothing against a corrupted record.
  • Wire failures into your evals. Every malformed output is a test case; capture it so the failure can't recur silently.

Our opinion

Our take: treat "parse the model's text output" as a legacy pattern and delete it. The single most common reliability bug we see in LLM features is a brittle extraction step - a prompt that begs for JSON, a regex that mostly works, and a try/catch that swallows the rest. It's entirely avoidable now. Schema-enforced structured output isn't an advanced technique; it's the baseline for any LLM output a machine will read.

We'd add the discipline that separates a demo from a product: the schema is a contract, and you enforce it on both ends. Constrain generation and validate on receipt. Belt and braces isn't paranoia when the alternative is a silent data-corruption bug that only shows up in aggregate weeks later. This is the same reliability-first posture behind designing a backend an agent can use - the output has to be trustworthy before anything acts on it.

How Ashvara helps

We build AI features where the model's output is load-bearing, and we build them so the JSON can't break the pipeline: schema-enforced structured output, validation at every boundary, retries on the high-stakes paths, and the failures wired into evals. You get an AI integration that behaves like software - predictable, typed, testable - instead of a text generator you're hoping parses.

If you've got an AI feature whose output feeds real systems, that's exactly the AI solutions work we do. Talk to us and we'll make the model's output something you can build on.

Source: 2026 LLM structured-output guides (three tiers - prompting ~80-95%, JSON mode ~95-99%, constrained decoding ~100% schema-valid; provider strictness varies) - see the guide to structured outputs and function calling.

Share this article
S
Sahil Jain

Founder at Ashvara, a studio that builds software end to end - mobile, web, AI, and the systems behind them. Writes about shipping products that last.

Building something? Let's talk.