@cldmv/jsonv

中文文档
1.2.2发布于 2026/11/07Apache-2.0TypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 8382

Modern JSON parser extending JSON5 with ES2015-2025 features, year-based API

原始使用文档
文档目录23 节
  1. ✨ What's New
  2. Latest: v1.2.2 (November 2026)
  3. Recent Releases
  4. 🚀 Key Features
  5. 📦 Installation
  6. Requirements
  7. Install
  8. 🚀 Quick Start
  9. 📅 Year‑Pinned API
  10. 🔧 API Surface
  11. Parse options (selected)
  12. Parse modes
  13. Stringify options (selected)
  14. 🛡 Errors
  15. 🌳 AST for Tooling
  16. 🔗 Internal References
  17. 🧰 Year Utilities
  18. 🔍 Diagnostics
  19. 🛠 Tooling
  20. 📚 Documentation
  21. 🤝 Contributing
  22. 🔗 Links
  23. 📄 License

@cldmv/jsonv

@cldmv/jsonv is a modern JSON parser and serializer that extends JSON5 with ES2015–2025 literals and year-pinned APIs. It is a static data format: JSON5 plus binary/octal literals, BigInt, numeric separators and template literals, with every feature gated by the ECMAScript year that introduced it.

On top of the literal syntax, jsonv adds internal references — file-scoped values that refer to other keys in the same document, forward references included — while forbidding executable syntax: no functions, classes, computed keys or shorthand properties. The parser is hand-written and has zero runtime dependencies.

JSON5 with modern literals and internal references, pinned to the ECMAScript year you choose.

npm version npm downloads GitHub downloads Last commit npm last update coverage

Contributors Sponsor shinrai


✨ What's New

Latest: v1.2.2 (November 2026)

  • Tooling release, no library changes — the vitest config now uses devCondition() from @cldmv/configs, so tests really run against src/ through the jsonv-dev export condition, and the type scripts are renamed to the fleet names types:check and types:build (#121, #123). The parser and every public specifier are unchanged.
  • View full v1.2.2 Changelog

Recent Releases

  • v1.2.1 (November 2026) — engines.node is >=18.0.0 again; the 22.22.0 toolchain floor moves to devEngines (Changelog)
  • v1.2.0 (November 2026) — CLDMV library layout: a tsup build, CommonJS wrappers beside the ESM files, and a working jsonv-dev condition in place of the broken json-dev one; declared Node.js >=22.22.0 and dropped the broken ./test/* export (#112) (Changelog)
  • v1.1.5 (October 2026) — dev toolchain refresh: vitest 5.0.3, eslint 10.12.0 and @cldmv/vitest-runner 1.5.3; no runtime code changed (Changelog)
  • v1.1.4 (October 2026) — require() returns the API synchronously instead of a Promise, and @cldmv/jsonv/year-resolver gains its missing CommonJS wrapper (Changelog)

📚 For complete version history and detailed release notes, see the docs/changelog/ folder.


🚀 Key Features

  • JSON5 superset (comments, trailing commas, single quotes, hex, etc.)
  • Year‑pinned APIs: @cldmv/jsonv/2011, /2015, /2020, /2021 (2022–2025 re‑export 2021)
  • Modern literals: binary/octal, BigInt, numeric separators
  • Internal references and template interpolation (ES2015+), including forward references
  • Diagnostics: diagnose() and info() for year + feature detection
  • Stringify with json/json5/jsonv modes, BigInt strategies, and raw JSON passthrough
  • Dynamic year loading and resolver utilities (loadYear, resolveYear)
  • Positioned AST, tokens and comments for tooling (parseToAst())
  • Zero dependencies, hand‑written parser

📦 Installation

Requirements

  • Node.js 18.0.0 or later for import (the package's engines range). jsonv has no dependencies and also runs in browsers.
  • require() loads the ESM build through Node's require(esm), so it needs Node.js ^20.19.0 or >=22.13.0. On older Node.js the CommonJS entry fails with a message telling you to use import() instead.
  • Developing this package needs Node.js 22.22.0 or later (devEngines).

Install

npm install @cldmv/jsonv

🚀 Quick Start

import { parse, stringify } from "@cldmv/jsonv";

const config = parse(`{
  port: 8080,
  host: "localhost",
  url: \`http://\${host}:\${port}\`,
  maxConnections: 1_000_000,
  bigValue: 9007199254740992n
}`);

const text = stringify(config);

CommonJS works the same way, synchronously:

const { parse } = require("@cldmv/jsonv");

parse("{ a: 1 }"); // { a: 1 }

📅 Year‑Pinned API

Pin a year for stable grammar rules:

import { parse } from "@cldmv/jsonv/2021"; // numeric separators + BigInt
import { parse as parse2015 } from "@cldmv/jsonv/2015"; // binary/octal + templates
import { parse as parse2011 } from "@cldmv/jsonv/2011"; // JSON5 base

See docs/feature-matrix.md and docs/versioning-and-exports.md.


🔧 API Surface

Main entry: src/index.mts

Parse options (selected)

  • year: 2011–2025 (defaults to latest)
  • mode: jsonv (default) | json5 (exactly JSON5 1.0) | json (exactly RFC 8259 JSON); see Parse modes
  • allowInternalReferences: default true
  • strictBigInt: require n for unsafe integers (default false)
  • strictOctal: require 0o (reject legacy 0755, default false)
  • tolerant: collect every syntax error instead of stopping at the first; parseWithOptions then throws them together as one JsonvAggregateSyntaxError (see Errors)
  • preserveComments: return comments (with positions) from Parser#parse(); see AST for tooling

Parse modes

mode: "json" accepts exactly RFC 8259 JSON and mode: "json5" accepts exactly JSON5 1.0; mode: "jsonv" (the default) enables every jsonv feature of the selected year. A feature outside the mode throws a positioned JsonvSyntaxError with code: "FEATURE_NOT_ALLOWED_IN_MODE" naming the feature and the mode, and an unknown mode value throws a TypeError. parse() takes the options object in place of the reviver:

import { parse } from "@cldmv/jsonv";

parse('{"a": [1, 2]}', { mode: "json" }); // { a: [1, 2] }
parse("{ a: 1, }", { mode: "json" }); // throws: Unquoted keys not allowed in JSON mode at line 1, column 2
parse("{ a: 1, b: a }", { mode: "json5" }); // throws: Internal references not allowed in JSON5 mode at line 1, column 11

The full feature × mode table is in docs/json5-compatibility.md.

Stringify options (selected)

  • mode: jsonv | json5 | json
  • bigint: native | string | object
  • singleQuote, trailingComma, unquotedKeys
  • preserveNumericFormatting

Full types: src/api-types.mts


🛡 Errors

Parse failures throw JsonvSyntaxError (extends SyntaxError, name stays "SyntaxError"), with structured position info alongside the message:

import { parse, JsonvSyntaxError } from "@cldmv/jsonv";

try {
    parse("{ a: 1, }");
} catch (err) {
    if (err instanceof JsonvSyntaxError) {
        console.log(err.line, err.column, err.offset); // 1-based line, message-matching column, 0-based offset
    }
}

This applies to every parse entry point (year-pinned APIs included) and every kind of positioned error — lexer-level (unterminated strings, invalid escapes, year-gated feature checks) and parser-level (unexpected tokens, strict-mode violations) alike.

With tolerant: true, the parser recovers at the next property or element boundary after a syntax error and keeps going. If any syntax error was collected, parseWithOptions (year-pinned APIs included) throws a single JsonvAggregateSyntaxError and does not evaluate the document. It is a JsonvSyntaxError whose own line/column/offset/code are the first error's, whose message is the first error's message followed by the total count, and whose errors array holds every error in source order, each a JsonvSyntaxError with its own position and code (the same error a strict parse would throw for it). A lexical error is reported through the same aggregate. Input without syntax errors evaluates exactly as it does without tolerant:

import { parseWithOptions, JsonvAggregateSyntaxError } from "@cldmv/jsonv";

try {
    parseWithOptions("{ a: 1,, b: 2,, c: }", { tolerant: true });
} catch (err) {
    if (err instanceof JsonvAggregateSyntaxError) {
        err.message; // "Expected property key, got COMMA at line 1, column 7 (3 syntax errors in total)"
        err.errors.map((e) => [e.line, e.column, e.code]); // [[1, 7, "PARSE_ERROR"], [1, 14, "PARSE_ERROR"], [1, 19, "PARSE_ERROR"]]
    }
}

parseToAst never throws for collected errors; it returns them in errors.

Internal-reference resolution failures (an unresolved or circular internal reference) throw the sibling JsonvReferenceError (extends ReferenceError, name stays "ReferenceError") instead, with the same structured line/column/offset/code shape, pointing at the offending reference:

import { parseWithOptions, JsonvReferenceError } from "@cldmv/jsonv";

try {
    parseWithOptions("{ a: missing }");
} catch (err) {
    if (err instanceof JsonvReferenceError) {
        console.log(err.line, err.column, err.offset);
    }
}

🌳 AST for Tooling

parseToAst() returns the positioned AST without evaluating it, for linters, formatters and editors:

import { parseToAst } from "@cldmv/jsonv"; // also exported from "@cldmv/jsonv/parser"

const { program, comments, tokens, errors } = parseToAst("// port\n{ port: 8080 }");
program.body.properties[0].key; // { type: "Identifier", name: "port", loc: { start: { line: 2, column: 2, offset: 10 }, ... } }
comments[0].value; // " port"

Every node, token and comment carries loc: { start, end } with { line, column, offset } positions (\n, \r\n, \r, U+2028 and U+2029 each count as one line break). Property keys are positioned Literal / Identifier nodes, and Property.loc spans key through value. parseToAst() never throws for invalid input: lexical and parse errors are both collected in errors (with code, line, column and offset), and tolerant: true recovers from both and reports every one. See docs/ast.md for the node reference.


🔗 Internal References

{ port: 8080, backup: port, url: `http://${host}:${port}` }

Rules: file‑scoped only, forward references supported, no circular refs.


🧰 Year Utilities

import { loadYear, getLoadedYear } from "@cldmv/jsonv/loader";
import { resolveYear, isPublishedYear, getPublishedYears } from "@cldmv/jsonv/year-resolver";

const jsonv2023 = await loadYear(2023); // resolves to 2021
const resolved = getLoadedYear(2017); // 2015
const published = getPublishedYears(); // [2011, 2015, 2020, 2021]
const isPublished = isPublishedYear(2021); // true
const nearest = resolveYear(2024); // 2021

🔍 Diagnostics

diagnose() returns detected year/features + compatibility flags (json, json5). info() returns only detected year + parsed value.


🛠 Tooling

  • ESLint plugin: published separately as @cldmv/eslint-plugin-jsonv (this repo's lint config consumes the published package). For local co-development, clone that repo under the gitignored plugins/eslint-plugin-jsonv/ path and run npm run build:plugin to link it against this repo's current build.
  • Prettier plugin: published separately as @cldmv/prettier-plugin-jsonv for formatting .jsonv files.
  • VS Code language support: published separately as jsonv-vscode; clone under the gitignored plugins/vscode-jsonv/ for local co-development.

📚 Documentation

  • Feature Matrix — features by ECMAScript year, lexical rules and excluded syntax
  • Versioning & Exports — year-pinned entry points, the root alias, and ESM / CommonJS loading
  • JSON5 Compatibility — how jsonv relates to JSON5 and the json / json5 / jsonv parse modes
  • AST and Parser API — parseToAst(), node types, positions, tokens and comments for tooling
  • Test Fixtures — per-year features/ and violations/ fixture layout
  • Changelog — release notes for every version

CodeFactor OpenSSF Scorecard npms.io score npm unpacked size Repo size


🤝 Contributing

Contributions are welcome — open an issue or a pull request on GitHub.

npm run build     # clean → tsup → types → generated years + CommonJS wrappers
npm test          # Vitest, then the CommonJS entry tests
npm run lint      # ESLint v9 config

Build layout. tsup compiles src/**/*.mts file by file into dist/ (no bundling, so every year module and the shared parser stay separate files). The CommonJS entry is hand-written in src/index.cjs and copied verbatim to dist/index.cjs, beside dist/index.mjs; it loads the ESM build through require(esm). npm run generate:years writes the forwarding modules for unpublished years and a dist/years/<name>.cjs wrapper beside every dist/years/<name>.mjs. Declarations go to dist/types/.

The jsonv-dev condition. In a checkout, the jsonv-dev export condition maps import of @cldmv/jsonv, @cldmv/jsonv/parser and @cldmv/jsonv/<year> to the TypeScript source in src/. The test suite runs with it (Vitest compiles the .mts files), so tests exercise src/ without a build. Plain Node.js can't run the source directly (it imports its siblings by their built .mjs names), so outside a TypeScript-aware tool use the build. require() is never mapped to src/: there is no src/index.mjs for src/index.cjs to load, so CommonJS callers in a checkout always get dist/, with or without the condition. npm run test:cjs builds first and checks exactly that.

  • Test runner: npm test (Vitest via @cldmv/vitest-runner, then node:test checks of the built CommonJS entry)
  • Fixtures: tests/fixtures/ with features/ and violations/ per year
  • See tests/fixtures/README.md for layout

Contributors Sponsor shinrai



📄 License

GitHub license npm license

Apache-2.0 © Shinrai / CLDMV

版本与发布记录

@cldmv/jsonv 共发布 16 个版本,首次发布于 2026/01/19;过去 12 个月发布了 16 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.2.2latest2026/11/072 天前
1.2.12026/11/027 天前
1.2.02026/11/028 天前
1.1.52026/10/1328 天前
1.1.42026/10/051 个月前
1.1.32026/10/031 个月前

关于 @cldmv/jsonv 的常见问题

@cldmv/jsonv 是什么?

Modern JSON parser extending JSON5 with ES2015-2025 features, year-based API

如何安装 @cldmv/jsonv?

在项目目录运行 npm install @cldmv/jsonv,或使用 pnpm add / yarn add / bun add。

@cldmv/jsonv 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cldmv/jsonv 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@cldmv/jsonv 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@cldmv/jsonv 可以商用吗?

@cldmv/jsonv 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@cldmv/jsonv 的下载量有多少?

根据 npm 官方下载统计,@cldmv/jsonv 在 2026/10/10 – 2026/11/08 这 30 天内被下载 8,382 次,日均约 279 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cldmv/jsonv 还在维护吗?

最新版本 1.2.2 发布于 2026/11/07(2 天前);至今共发布 16 个版本,其中过去 12 个月发布了 16 个;首次发布于 2026/01/19。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。