How to Fix Broken JSON from LLMs
LLMs are probabilistic. Your code is deterministic. Shim bridging the gap.
Failure: JSON Truncation
The Problem: LLMs hit token limits or timeout mid-response. You receive an incomplete JSON object that `JSON.parse()` rejects.
// Received Output:
{"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": Result: Production crash. Loss of data. Broken UI.
The Shim Fix:
Shim detects the truncation and instantly injects the missing closing brackets and braces to make the JSON syntactically valid.
// Repaired by Shim:
{"users": [{"id": 1, "name": "Alice"}, {"id": 2}]} Latency: <0.05ms
Failure: Markdown Code Fences
The Problem: Even in "JSON mode," LLMs often wrap outputs in markdown backticks: ```json ... ```.
The Shim Fix:
Shim automatically strips markdown indicators, whitespace, and non-JSON preamble text before your parser ever sees it.
Action: Intercept & Strip
Failure: Schema Drift
The Problem: The LLM returns a string when you expect a number, or neglects a required field. Downstream services fail validation.
Type Coercion
LLM returns "30" for age. Your DB expects number. Shim coerces the type instantly.
Value Recovery
LLM returns null for a required boolean. Shim defaults or repairs based on your schema.
Implementation
Receive. Repair. Return.
Shim sits between your LLM and application logic.
const response = await fetch('https://api.shim.so/v1/repair', {
method: 'POST',
headers: { 'Authorization': 'Bearer sk_xxx' },
body: JSON.stringify({
raw_output: llmOutput,
schema: myJsonSchema // Optional
})
});
const { repaired, metadata } = await response.json();- Sub-millisecond repair time
- Zero data persistence policy
- Streaming compatible
Shim vs Alternatives
| Feature | Retries | FixingParser | Shim |
|---|---|---|---|
| Latency | 2 - 5s | Full output wait | <10ms total |
| Streaming | No | No (buffering) | Yes |
| Cost | 2x Tokens | High Infra | Flat rate |
| Confidence | None | None | Structured |