jsonpluck
v0.1.1
Published
Pluck valid JSON out of messy LLM output — strips markdown fences, fixes trailing commas, single quotes, comments, and truncation. Zero dependencies.
Downloads
290
Maintainers
Readme
jsonpluck
Pluck valid JSON out of messy LLM output — markdown fences, trailing commas, single quotes, comments, truncation — with zero dependencies.
You asked the model for JSON. You got:
Sure! Here's the data you requested:
```json
{
"title": "Quarterly Report",
"tags": ["finance", "q3",], // trailing comma + comment
'confidence': 0.87, // single quotes
}
```
Hope that helps!JSON.parse throws on every line of that. jsonpluck returns the object.
import { pluck } from "jsonpluck";
pluck(llmResponse);
// → { title: "Quarterly Report", tags: ["finance", "q3"], confidence: 0.87 }What it handles
- Markdown fences —
```json,```jsonc, or plain```. - Prose around the JSON — finds the first balanced
{…}/[…]. - Trailing commas, single quotes, “smart” quotes, unquoted keys.
//and/* */comments.- Python literals —
True/False/None. NaN/Infinity→null(valid JSON).- Truncated output — a response cut off mid-object/array/string is recovered
as the partial value, with a
truncatedflag so you can decide what to do.
Strictly-valid JSON takes a JSON.parse fast path, so there's no penalty for the
happy case.
Install
npm install jsonpluck
# or: pnpm add jsonpluck / yarn add jsonpluck / bun add jsonpluckAPI
pluck<T>(text, options?): T
Extract and parse JSON, throwing if nothing is recoverable.
const data = pluck<{ title: string }>(llmResponse);tryPluck<T>(text, options?): PluckResult<T>
Never throws. Returns a discriminated union you can branch on.
const r = tryPluck<MySchema>(llmResponse);
if (r.ok) {
use(r.value);
if (r.truncated) console.warn("recovered a partial value");
} else {
console.error(r.error);
}type PluckResult<T> =
| { ok: true; value: T; strict: boolean; truncated: boolean }
| { ok: false; error: string };repair(text, indent?): string
Return canonical JSON text (handy for logging or re-serialising).
repair("{'a':1,}"); // '{"a":1}'
repair("{'a':1}", 2); // '{\n "a": 1\n}'Options
| Option | Type | Default | Description |
| ---------------- | --------- | ------- | ------------------------------------------------------ |
| allowTruncated | boolean | true | Accept partial values from truncated input vs. fail. |
Low-level building blocks
import { extractCandidate, parseTolerant } from "jsonpluck";
extractCandidate(text); // → the JSON-ish substring (or null)
parseTolerant(jsonish); // → { value, strict, truncated }Why use it?
LLMs are probabilistic; structured-output modes help but don't eliminate stray
prose, fences, or truncation under token limits. Wrapping every parse in
jsonpluck turns a class of intermittent production crashes into recovered data.
- Zero dependencies — runs in Node, browsers, edge runtimes, and Workers.
- Fast path for valid JSON — no overhead when the model behaves.
- Honest about truncation — you get a flag, not a silent guess.
CLI
cat llm-response.txt | jsonpluck # repaired JSON to stdout
cat llm-response.txt | jsonpluck --pretty # pretty-printed
jsonpluck response.json --strict-truncation # exit 1 if truncatedA note on guarantees
jsonpluck recovers structure; it cannot invent data that the model never
produced. For a truncated array of 10 items where only 6 arrived, you get 6.
Validate the recovered value against your schema (e.g. with Zod) before trusting
it.
Contributors ✨
This project follows the all-contributors specification. Contributions of any kind are welcome — code, docs, bug reports, ideas, reviews! See the emoji key for how each contribution is recognized, and open a PR or issue to get involved.
Thanks goes to these wonderful people:
License
MIT © Tung Tran
