7 ms·
Show HN: Repair-JSON-stream – Fix broken JSON from LLM streaming (1.7x faster)
I've been building LLM-powered apps and kept hitting the same problem: when you stream JSON from OpenAI/Anthropic, it arrives incomplete mid-generation.
{"message": "I'm currently generating your resp
JSON.parse dies. You either wait for the full response (slow) or try to parse incrementally (hard).
I wrote a single-pass state machine that repairs broken JSON as chunks arrive.
Technical approach:
- Zero external dependencies - everything from scratch
- No regex (avoids ReDoS vulnerabilities)
- O(n) single-pass processing
- Stack-based context tracking
- Character classification via bitmask lookup table
- Works in Node.js, Deno, Bun, browsers, Cloudflare Workers
What it handles:
- Truncated strings and unclosed brackets
- Python constants (None, True, False)
- Single quotes, trailing commas, unquoted keys
- JSONP wrappers, MongoDB types (NumberLong)
- LLM "thinking" blocks and markdown fences
- String concatenation ("a" + "b")
The streaming benchmark shows 1.7x faster than jsonrepair - we avoid re-parsing the entire document on each chunk.
7KB minified. TypeScript-first with full type definitions.
Curious what edge cases others have hit - always looking to improve coverage.
- dmarwicke 9mo agodoes this handle the thinking blocks that claude puts in? those break json.parse constantly when it streams reasoning before the actual response
- prxtenses 9mo agoYes! We added that in v1.2.0 with the extract module Supported thinking block patterns: <thinking>...</thinking> (Claude) | <thought>...</thought> (DeepSeek) | <reasoning>...</reasoning> | <scratchpad>...</scratchpad> | Also handles markdown code blocks and common LLM prose like "Here's the JSON:" or "Hope this helps!"