
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
ai-json-safe-parse
Advanced tools
Parse malformed JSON from AI/LLM responses. Handles markdown code blocks, trailing commas, comments, unquoted keys, and more.
Parse malformed JSON from AI/LLM responses. Zero dependencies. Works in Node.js and browsers.
If you've built anything with ChatGPT, Claude, Gemini, or any other LLM, you've hit this: you ask for JSON and get back something that almost works — wrapped in markdown code blocks, sprinkled with trailing commas, decorated with smart quotes, or buried in a paragraph of explanation. JSON.parse chokes and your app breaks.
ai-json-safe-parse handles all of it. One function call, typed generics, no dependencies.
npm install ai-json-safe-parse
Works with any package manager (npm, yarn, pnpm, bun) and any runtime (Node.js, browsers, Deno, Cloudflare Workers, edge functions).
import { aiJsonParse } from 'ai-json-safe-parse'
// Typical LLM response with markdown code fences
const llmOutput = `Sure! Here's the JSON:
\`\`\`json
{
"sentiment": "positive",
"confidence": 0.95,
"keywords": ["great", "excellent", "loved it"]
}
\`\`\`
Let me know if you need anything else!`
const result = aiJsonParse<{
sentiment: string
confidence: number
keywords: string[]
}>(llmOutput)
if (result.success) {
console.log(result.data.sentiment) // "positive"
console.log(result.data.confidence) // 0.95
}
The library exports three functions. Pick the one that fits your error-handling style.
aiJsonParse<T>(text, options?) — Result objectReturns a discriminated union: { success: true, data: T } or { success: false, error: string }. Never throws.
import { aiJsonParse } from 'ai-json-safe-parse'
const result = aiJsonParse<{ name: string }>(llmOutput)
if (result.success) {
console.log(result.data.name)
} else {
console.error(result.error)
}
aiJsonSafeParse<T>(text, options?) — NullableReturns the parsed value or null. The simplest option when you just need the data.
import { aiJsonSafeParse } from 'ai-json-safe-parse'
const data = aiJsonSafeParse<{ name: string }>(llmOutput)
if (data) {
console.log(data.name)
}
You can also pass a fallback value — if parsing fails, you get the fallback instead of null:
const data = aiJsonSafeParse(llmOutput, { name: 'unknown' })
// data is always { name: string }, never null
aiJsonStrictParse<T>(text, options?) — Throws on failureReturns the parsed value or throws an Error. Use this when a parse failure should be exceptional.
import { aiJsonStrictParse } from 'ai-json-safe-parse'
const data = aiJsonStrictParse<{ name: string }>(llmOutput)
console.log(data.name)
The parser applies recovery strategies in order, from safest to most aggressive:
| Strategy | Mode | What it handles |
|---|---|---|
Direct JSON.parse | both | Already-valid JSON |
| Markdown extraction | both | ```json ... ```, ```jsonc ... ```, ```js ... ```, and bare code blocks |
| Unicode normalization | both | UTF-8 BOM, zero-width chars, smart quotes \u201C\u201D\u2018\u2019, em/en dashes \u2014\u2013, non-breaking spaces, ellipsis \u2026 |
| Bracket matching | both | JSON embedded in prose: "Here is the result: {...} hope that helps!" |
| Comment removal | aggressive | // line comments and /* block comments */ (preserves URLs) |
| Trailing comma removal | aggressive | {"a": 1,} and [1, 2,] |
| Single quote replacement | aggressive | {'name': 'Alice'} |
| Unquoted key fix | aggressive | {name: "Alice"} |
| Regex key-value extraction | aggressive | Severely broken JSON (last resort) |
// Markdown code blocks
aiJsonParse('```json\n{"key": "value"}\n```')
// JSON buried in a paragraph
aiJsonParse('The analysis shows {"score": 95, "grade": "A"} for this input.')
// Trailing commas (extremely common from LLMs)
aiJsonParse('{"items": ["a", "b", "c",],}')
// JavaScript-style objects with comments
aiJsonParse(`{
name: "Alice", // the user
age: 30, // in years
active: true,
}`)
// Smart quotes from copy-paste or GPT
aiJsonParse('{\u201Cname\u201D: \u201CAlice\u201D}')
// Em dashes in content
aiJsonParse('{"range": "10\u201420"}') // → {"range": "10-20"}
interface ParseOptions {
/**
* How aggressively to attempt repairs on malformed JSON.
* Default: 'aggressive'
*/
mode?: 'safe' | 'aggressive'
}
safe — Tries direct parse, markdown extraction, unicode normalization, and bracket matching only. Use this when data integrity is more important than recovery rate. Won't modify the JSON structure.
aggressive (default) — Additionally fixes syntax issues and falls back to regex extraction. Higher recovery rate, but may misinterpret severely malformed input.
// Only use safe recovery strategies
const result = aiJsonParse(text, { mode: 'safe' })
// Use all strategies (default)
const result = aiJsonParse(text, { mode: 'aggressive' })
Full generic type support. All exports are fully typed.
import { aiJsonParse, aiJsonSafeParse, aiJsonStrictParse } from 'ai-json-safe-parse'
import type { ParseResult, ParseSuccess, ParseFailure, ParseOptions } from 'ai-json-safe-parse'
interface MyResponse {
summary: string
score: number
tags: string[]
}
// All three functions accept a generic type parameter
const result = aiJsonParse<MyResponse>(text) // ParseResult<MyResponse>
const data = aiJsonSafeParse<MyResponse>(text) // MyResponse | null
const strict = aiJsonStrictParse<MyResponse>(text) // MyResponse (throws on failure)
Zero dependencies. Tree-shakeable ESM. The entire library is ~5KB unminified (~2KB gzipped).
Both ESM (import) and CommonJS (require) are supported via the exports field in package.json.
This library was extracted from the production codebase at LeadTruffle, where we use it to parse thousands of AI-generated JSON responses daily across our lead qualification, SMS automation, and voice AI pipelines. We run it in AWS Lambda (Node.js), Cloudflare Workers, and in-browser — so it had to be lightweight, dependency-free, and universal from day one.
After copy-pasting variations of this code across multiple services, it made sense to clean it up and share it. Thank you to LeadTruffle for supporting the open-source release.
The test suite covers valid JSON, markdown extraction, unicode edge cases, bracket matching, all aggressive-mode fixes, safe mode, real-world LLM outputs, and error cases.
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Type check
npm run lint
Tests use Vitest. To run them locally:
git clone https://github.com/a-r-d/ai-json-safe-parse.git
cd ai-json-safe-parse
npm install
npm test
Contributions are welcome! If you've hit an LLM output format that this library doesn't handle, please open an issue with the raw text — that's the most helpful thing you can provide.
To contribute code:
npm test to make sure everything passesnpm run lint to check typesPlease keep PRs focused — one fix or feature per PR.
Aaron Decker — ard.ninja / @a-r-d
CTO at LeadTruffle, a speed-to-lead platform for home service businesses. I've been a software engineer for 15+ years. After writing the same JSON-from-LLM parsing code across too many services, I decided to open source it. If you're building AI-powered products and burning time on malformed JSON, I hope this saves you some headaches.
FAQs
Parse malformed JSON from AI/LLM responses. Handles markdown code blocks, trailing commas, comments, unquoted keys, and more.
The npm package ai-json-safe-parse receives a total of 9 weekly downloads. As such, ai-json-safe-parse popularity was classified as not popular.
We found that ai-json-safe-parse demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.