eslint-plugin-jsonc

ESLint plugin that applies JavaScript-style linting, auto-fixing, and formatting rules to JSON, JSONC, and JSON5 files.

Tool
npm
v3.4.2
240stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
79/100Good
Development Activity88
Maintenance88
Community60
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
83/100Excellent
Architecture85
Code Quality90
Innovation75
Learning Curve80

eslint-plugin-jsonc extends ESLint so it can lint .json, .jsonc, and .json5 files the same way it lints JavaScript. Because JSON is a subset of JavaScript syntax, the plugin parses JSON with a purpose-built parser (jsonc-eslint-parser) that produces an ESLint-compatible AST under distinct node names, so ESLint core rules never misfire on it while the plugin’s own 40+ rules can catch JSON-specific problems: duplicate keys, disallowed comments, non-standard number literals, inconsistent key casing, and more.

Unlike processor-based JSON linters that hand ESLint a result without real source text or AST, eslint-plugin-jsonc implements ESLint’s newer Language Plugin API directly, which means directive comments (// eslint-disable-next-line), autofix, and interoperability with text-based plugins like eslint-plugin-prettier all work as expected. It also understands Vue single-file component custom blocks (<i18n> and similar) via vue-eslint-parser, and ships a jsonc/auto rule that mirrors whatever core ESLint rules a project already has configured, applying the JSON-appropriate equivalents automatically.

What You Get

  • 40+ rules covering duplicate keys, disallowed non-standard syntax (BigInt, octal, numeric separators), key ordering, key-name casing, and formatting (indent, comma-dangle, comma-style, spacing)
  • Ready-made flat configs: base, recommended-with-json, recommended-with-jsonc, recommended-with-json5, prettier (disables conflicting rules), and all
  • A jsonc/auto rule that derives JSON-appropriate equivalents of whatever core ESLint rules the project already enables
  • Custom language identifiers (jsonc/json, jsonc/jsonc, jsonc/json5, jsonc/x) implemented on ESLint’s Language Plugin API for first-class parsing, not a processor shim
  • Support for linting JSON embedded in Vue SFC custom blocks via vue-eslint-parser
  • Autofix support on the majority of formatting and syntax rules via eslint --fix

Common Use Cases

  • Enforcing consistent formatting and key ordering across config files (package.json, tsconfig.json, .eslintrc.json) in a monorepo
  • Catching invalid or non-standard JSON (trailing commas, comments, duplicate keys) before it reaches production config loading
  • Applying the same style rules a team already uses for JavaScript (indent, quote style, comma style) to its JSON files with no separate tool
  • Linting JSONC files such as VS Code’s settings.json or tsconfig.json where comments are allowed but stray syntax errors still need catching
  • Validating JSON embedded inside Vue single-file component custom blocks (i18n translation blocks, etc.)

Under The Hood

Architecture The plugin separates concerns cleanly across lib/language/ (a custom JSONCLanguage/JSONCSourceCode implementation of ESLint’s Language Plugin API that produces JSON, JSONC, JSON5, and ‘extended’ parsing modes), lib/rules/ (44 independent rule modules, each a self-contained createRule(...) module), lib/configs/flat/ (pre-composed Linter.Config[] arrays per JSON variant), and lib/utils/ (shared casing, AST, and auto-fix helpers). A generated lib/utils/rules.ts (produced by tools/update.ts, never hand-edited) wires all rule modules into the plugin’s rules export, keeping the rule registry, README tables, and docs pages in sync from one source of truth. The jsonc/auto rule is the most structurally interesting piece: it walks a project’s already-configured core ESLint rules at lint time and dynamically re-applies JSON-equivalent versions of them via a sub-context proxy, rather than requiring separate manual configuration.

Tech Stack Written in TypeScript, published as ESM-only ("type": "module"), and built with tsdown. Its own parsing is delegated to jsonc-eslint-parser (a sibling project by the same author), with @eslint/core and @eslint/plugin-kit providing the Language Plugin API surface required for ESLint 9.38+. synckit bridges async rule config resolution into ESLint’s synchronous rule API, and vue-eslint-parser is an optional peer for Vue SFC custom-block support. Documentation is a full VitePress site with a live playground; releases are automated with Changesets.

Code Quality Every one of the 44 rules has a matching test file under tests/lib/rules/ (58 test files total across rules, language, configs, and utils), run through a project-specific RuleTester wrapper on top of ESLint’s own tester, with c8 coverage reporting. The plugin lints and type-checks itself (tsc --noEmit, plus its own dogfooded ESLint config using @ota-meshi/eslint-plugin and typescript-eslint), and CI runs on GitHub Actions (NodeCI.yml) across supported Node versions. No swallowed errors or untyped escape hatches were found in the core rule/language code.

API Design Configuration follows ESLint 9’s flat-config conventions exactly, so adopting the plugin is a matter of spreading one of its pre-built configs['recommended-with-*'] arrays into an existing eslint.config.js — no separate CLI or build step. Language identifiers (jsonc/json, jsonc/jsonc, etc.) map directly onto ESLint’s own language config field, keeping the mental model identical to linting JavaScript. The one added-complexity: choosing between four json/jsonc/json5/x language variants and five overlapping config presets requires reading the docs once, though the README’s comparison to @eslint/json and to processor-based alternatives makes the tradeoffs explicit.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search