# best-effort-json-parser

> Parse incomplete json text in best-effort manner

Latest version **1.5.1** (published 2026-06-26) · BSD-2-Clause license · 0 weekly downloads

## Install

```sh
npm install best-effort-json-parser
pnpm add best-effort-json-parser
yarn add best-effort-json-parser
bun add best-effort-json-parser
```

## Health

**Score 65/100 (B)** — status: active.

Positive: has types; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads; no esm support.

## Facts

| | |
|---|---|
| Version | 1.5.1 |
| Published | 2026-06-26 |
| First published | 2020-12-20 |
| Weekly downloads | 0 |
| License | BSD-2-Clause |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 0 |
| Unpacked size | 71.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 278 |
| Author | Beeno Tung |
| Maintainers | beenotung |
| Keywords | json, parser, auto-fix, auto-repair, best-effort |

## Links

- npm: https://www.npmjs.com/package/best-effort-json-parser
- Repository: https://github.com/beenotung/best-effort-json-parser
- Homepage: https://github.com/beenotung/best-effort-json-parser#readme
- Issues: https://github.com/beenotung/best-effort-json-parser/issues
- npm.io page: https://npm.io/package/best-effort-json-parser

## Alternatives

- [@mapbox/jsonlint-lines-primitives](https://npm.io/package/@mapbox/jsonlint-lines-primitives.md) — 5.3M weekly downloads
- [reftools](https://npm.io/package/reftools.md) — 3.5M weekly downloads
- [@hey-api/openapi-ts](https://npm.io/package/@hey-api/openapi-ts.md) — 3.5M weekly downloads
- [@mapbox/geojson-rewind](https://npm.io/package/@mapbox/geojson-rewind.md) — 2.4M weekly downloads
- [turbo-stream](https://npm.io/package/turbo-stream.md) — 1.7M weekly downloads

## Recent versions

- 1.5.1 (latest) — 2026-06-26
- 1.5.0 — 2026-06-26
- 1.4.1 — 2026-05-25
- 1.4.0 — 2026-03-11
- 1.3.0 — 2026-03-10
- 1.2.1 — 2025-07-19
- 1.2.0 — 2025-07-19
- 1.1.3 — 2025-02-14
- 1.1.2 — 2024-05-23
- 1.1.1 — 2024-05-16
- 1.1.0 — 2024-05-09
- 1.0.1 — 2023-01-09
- 1.0.0 — 2022-09-09
- 0.1.1 — 2021-01-31
- 0.1.0 — 2020-12-20
- … 1 more at https://npm.io/package/best-effort-json-parser/versions

## README

# best-effort-json-parser

Parse incomplete JSON text in best-effort manner. Useful for partial JSON responses, broken network packages, LLM responses with markdown fences or exceeding token limits, and configuration files with comments.

[![npm Package Version](https://img.shields.io/npm/v/best-effort-json-parser)](https://www.npmjs.com/package/best-effort-json-parser)
[![Minified Package Size](https://img.shields.io/bundlephobia/min/best-effort-json-parser)](https://bundlephobia.com/package/best-effort-json-parser)
[![Minified and Gzipped Package Size](https://img.shields.io/bundlephobia/minzip/best-effort-json-parser)](https://bundlephobia.com/package/best-effort-json-parser)
[![npm Package Downloads](https://img.shields.io/npm/dm/best-effort-json-parser)](https://www.npmtrends.com/best-effort-json-parser)

## Features

- Typescript support
- Isomorphic package: works in Node.js and browsers
- Comment support: `// inline`, `/* multi-line */`, and `<!-- HTML-style -->` comments
- Markdown code block support: extracts JSON from ` ```json ` or ` ``` ` fences during parsing; remaining text is available via `parse.lastParseReminding`

## Installation

```bash
npm install best-effort-json-parser
```

You can also install `best-effort-json-parser` with [pnpm](https://pnpm.io/), [yarn](https://yarnpkg.com/), or [slnpm](https://github.com/beenotung/slnpm)

## Usage Example

### Parsing incomplete JSON text

If the string, object, or array is not complete, the parser will return the partial data.

```typescript
import { parse } from 'best-effort-json-parser'

let data = parse(`[1, 2, {"a": "apple`)
console.log(data) // [1, 2, { a: 'apple' }]
```

### Parsing JSON with comments

Multiple types of comments are supported:

```typescript
import { parse } from 'best-effort-json-parser'

let config = parse(`{
  "database": {
    "host": "localhost", // database server
    "port": 5432, /* default port */
    "ssl": true
  },
  "features": ["auth", "api"] <!-- injected by LLM -->
}`)
```

Comments inside strings are preserved and not treated as comments:

```typescript
let data = parse(`{
  "inline_comment": "// this is not a comment",
  "block_comment": "/* neither is this */",
  "html_comment": \`<!-- \${variable} -->\`,
  "value": 42
}`)
```

**Note:** The parser also supports template literals with backticks (\`) for strings, in addition to single and double quotes.

### Parsing JSON in markdown code blocks

When LLMs return JSON inside markdown fences, `parse()` extracts the first block automatically:

```typescript
import { parse } from 'best-effort-json-parser'

let llmResponse = `\`\`\`json
[
  {"id": 1, "username": "alice"},
  {"id": 2, "username": "bob"}
]
\`\`\``

let data = parse(llmResponse)
console.log(data) // [{ id: 1, username: 'alice' }, { id: 2, username: 'bob' }]
```

Both ` ```json ` and plain ` ``` ` fences are supported. If no fence is found, the input is parsed as-is.

When the response contains multiple fenced blocks, loop on `parse.lastParseReminding` to parse each block until it's empty.

Text after fences is also parsed. Most of them will be parsed as string, but substrings like `true` or `123` can become boolean or number, so filter by the JSON shape you expect from the markdown text (e.g. array or object):

Given markdown text with multiple fenced blocks:

````markdown
Part 1:

```json
[
  { "id": 1, "username": "alice" },
  { "id": 2, "username": "bob" }
]
```

Part 2:

```
[
  { "id": 3, "username": "charlie" },
  { "id": 4, "username": "david" }
]
```

Ending text.
````

```typescript
let parts: any[] = []
for (let acc = text; acc; acc = parse.lastParseReminding!) {
  parts.push(parse(acc))
}
// expect arrays from the LLM — skip prose parsed as string/number/boolean
parts = parts.filter(part => Array.isArray(part))

// if you expect objects instead:
// parts = parts.filter(part => typeof part === 'object' && part !== null && !Array.isArray(part))

// parts[0] => [{ id: 1, username: 'alice' }, { id: 2, username: 'bob' }]
// parts[1] => [{ id: 3, username: 'charlie' }, { id: 4, username: 'david' }]
```

Fences inside JSON string values are preserved and not treated as markdown:

````typescript
let data = parse(`{
  "snippet": "\`\`\`json\\n[1,2,3]\\n\`\`\`"
}`)
// { snippet: '```json\n[1,2,3]\n```' }
````

## Error Logging

By default, the parser logs errors to `console.error`. You can control error logging behavior:

```typescript
import {
  disableErrorLogging,
  enableErrorLogging,
  setErrorLogger,
} from 'best-effort-json-parser'

// Disable error logging completely
disableErrorLogging()

// Re-enable error logging (default behavior)
enableErrorLogging()

// Set a custom error logger
setErrorLogger((message, data) => {
  // Your custom logging logic here
  console.log('Custom error:', message, data)

  // Common destinations for error data:
  // - Database storage for analysis
  // - File system logging
  // - Third-party services (Sentry, LogRocket, etc.)
  // - Monitoring and alerting systems
})
```

## Typescript Signature

```typescript
// Main parse function
function parse(s: string | undefined | null): any

// Parse namespace with additional properties
namespace parse {
  lastParseReminding: string | undefined // remaining text after the last parse (e.g. trailing markdown blocks)
  onExtraToken: (text: string, data: any, reminding: string) => void | undefined
}

// Error logging functions
function setErrorLogger(logger: (message: string, data?: any) => void): void
function disableErrorLogging(): void
function enableErrorLogging(): void
```

See more examples in [parse.spec.ts](./src/parse.spec.ts)

## License

This is free and open-source software (FOSS) with
[BSD-2-Clause License](./LICENSE)

---
_Source: https://npm.io/package/best-effort-json-parser · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
