JSON extraction is the task of turning unstructured text — a web page, a support ticket, an invoice, a contract — into a structured object with named fields, so the rest of a system can actually use it. It's one of the most common things production LLM systems are asked to do, precisely because so much real business data starts as free text that needs to become something a database, a dashboard, or another program can consume directly.
It shows up constantly: pulling fields out of documents for a data pipeline, turning a customer message into arguments a tool can call, structuring the output of one AI step so the next step in an agent workflow can read it. Multiple independent technical sources converge on the same conclusion — structured, schema-conforming output has become the standard way production systems get usable data out of an LLM, not an edge case.
For every field in a JSON extraction schema, ExactRoute detects, with evidence rather than a guess, whether the value is already solved by a pattern, a known vocabulary, a named-entity model, an external lookup, or whether it genuinely needs a frontier model — and shows its work for each one.
ExactRoute also packages the result: deterministic code covering whichever combination of regex, NER, and knowledge-graph lookups each field actually needs, plus a clear, explicit list of whatever still genuinely needs an LLM call — bundled as something a customer can drop directly into their own pipeline. Your data and your infrastructure stay yours; ExactRoute doesn't host or run anything on your behalf.
The eight cases below are real examples of this in action.
A quick look at ExactRoute on a dataset modelled on a real customer's: 20 LLM calls, each returning a JSON of 17 fields. ExactRoute scores every choice on three Cs, and works through five steps: detection, refinement and validation, model comparison, package generation, and a package run.
Does the same input give the same answer every run? Rules, lookups and pinned local models always do. A model call may not, even across versions of the same model.
How often is the answer wrong, measured against your own logged outputs? Cheaper only counts if it isn't worse.
How much of today's token spend remains once the fields that don't need a model stop going to one?
Request early access, and try it on your own dataThe same run in detail: the field-by-field verdicts, validating and accepting local models, the comparison against five LLMs, and the package you would deploy.
Each one is a real, tested case — its own dataset, its own evidence. Open any of them.
Know which fields need the model. Prove the rest.
Every number on this page came from testing against real, logged data — not a synthetic example built to make a point. Where something didn't work as hoped, we said so, because a detection system that only reports its wins isn't one you should trust with a production pipeline.
See how ExactRoute applies this to your own extraction taskThe problem: an invoice-processing pipeline sending every field to a frontier model, including ones a five-line pattern already handles perfectly. What this shows: some fields are fully solved by pattern matching, and the data proves it — not a guess about "structured-looking" text.
100% coverage under pure regex, measured against every real logged row — no model involved, ever, for these two fields.
The problem: extracting names, dates, and other entities that vary too much for a fixed list, but are still just sitting in the text, not being invented. What this shows: a real named-entity extraction job, not generation — a lightweight NER pass replaces the LLM call entirely.
100% span-extractable — the exact value is always present, verbatim, in the source. This is exactly what NER does; no reasoning required.
The problem: paying for a fresh LLM call to re-derive a fact about a company that was already true yesterday and will still be true tomorrow. What this shows: a fact that never needed to be generated at all — never stated in the source text, but never different either. That combination means it belongs in a lookup, not a prompt.
Zero containment, perfectly stable. Absent from the source text on every one of 20 real calls, yet identical every time — the exact signature of a fact, not a generation.
Proven buildable, not theoretical: using a real company's actual SEC filing, we built a real graph answering 3-hop ownership chains and fractional-split ownership deterministically.
The problem: over-optimizing is its own failure mode, trying to cache or cheaply approximate a field that genuinely needs fresh reasoning every time. What this shows: the honest contrast that makes the rest credible — not everything is a lookup, and the system has to say so plainly rather than force a shortcut that does not exist.
100% unique across every call — no two pages produced the same theme. Correctly recognized as document-specific, not an external fact.
A subtler check: the theme's exact wording is never on the page, but its individual words mostly are — 0.78–1.00 overlap with the source, measured. Useful for catching hallucination, not for replacing the LLM.
The problem: a knowledge-graph lookup is only as good as its key. If your data calls the same company three different things, a naive lookup keyed on the literal text fails silently on two of the three mentions, returning nothing, or worse, the wrong company's data. What this shows: the lookup key itself needs a real resolution step first, normalizing "TMC" and "Toyota Motors" to the same canonical entity, before the graph lookup can even be attempted. Skipping this step is exactly how a KG-based pipeline quietly fails in production.
Same company, two different raw mentions. The KG lookup for industry only works once this resolution happens first — detected and now surfaced explicitly, not silently assumed.
The problem: a shared name across unrelated real companies is a genuine worst case for automated entity resolution. Get it wrong and you have silently attached the wrong company's facts to your data. What this shows: we tried to break our own system on purpose. It broke in an instructive way, and we are saying so rather than hiding it.
A name shared by three real, unrelated companies: an airline, a plumbing-fixtures maker, an electronics manufacturer — all called "Delta." Disambiguating it requires reading context, not pattern-matching.
Our tier logic misjudged this as "simple, lite-model-friendly" — because the shape (short values, few repeats) looked easy. It wasn't. The logic sees shape, not the difficulty of the reasoning underneath. Tracked as an open problem, not smoothed over.
The problem: when a statistical check and an LLM-based check disagree, silently trusting either one risks either missing a real fact or treating noise as signal. What this shows: not every case resolves cleanly, and the system says so, surfacing both signals for a person to decide, rather than quietly picking a side.
A statistical check said "not stable — wording varies too much." A second, LLM-based check correctly recognized this as entity-name normalization, not real variation. Both signals shown side by side; a person decided. That decision now propagates to every downstream output.
The problem: teams often assume cross-checking one model against another catches errors, but that only works if the models fail differently. What this shows: not inconsistency between models. The opposite, and more concerning: two separate frontier models agreeing on the same wrong answer, which no amount of model-switching would have caught.
Testing the same extraction task across models, Claude Sonnet 5 and Claude Opus 4.8 both fabricated a value on the exact same field — one that should have returned null. They didn't disagree. They converged on the same wrong answer.
Switching models wouldn't have caught this. A deterministic check — does this value exist anywhere, yes or no — catches it every time, because it isn't guessing at all.