Skip to content

docs: create dedicated documentation for JSON #106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Jun 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
06a8a48
docs: create dedicated documentation for JSON
lumirlumir May 31, 2025
b094570
wip: fix a typo
lumirlumir May 31, 2025
b08c275
wip: update `README.md`
lumirlumir May 31, 2025
119e8f7
wip: update template
lumirlumir Jun 1, 2025
a85d9ec
wip: update URL and ESLint config file
lumirlumir Jun 1, 2025
2262118
wip
lumirlumir Jun 2, 2025
3773815
wip: recommended
lumirlumir Jun 2, 2025
aebaa41
wip
lumirlumir Jun 2, 2025
02c8d60
wip
lumirlumir Jun 2, 2025
f3c507e
wip: complete `no-duplicate-keys.md`
lumirlumir Jun 2, 2025
64e034c
wip: complete `no-empty-keys.md`
lumirlumir Jun 2, 2025
7c94b3e
wip: update `no-empty-keys`
lumirlumir Jun 3, 2025
f0f0e4b
wip: complete `no-unnormalized-keys.md`
lumirlumir Jun 3, 2025
b46e489
wip: fix link
lumirlumir Jun 3, 2025
99bc347
wip: complete `no-unsafe-values.md`
lumirlumir Jun 3, 2025
246837c
wip: prettier ignore
lumirlumir Jun 3, 2025
649fe06
Update no-unnormalized-keys.md
lumirlumir Jun 3, 2025
85a5f41
Update no-unsafe-values.md
lumirlumir Jun 3, 2025
4b03dc6
wip
lumirlumir Jun 3, 2025
4bc724e
Merge branch 'docs-create-dedicated-docs-for-json' of https://github.…
lumirlumir Jun 3, 2025
25e2a0c
wip
lumirlumir Jun 3, 2025
176c71a
wip: complete `sort-keys.md`
lumirlumir Jun 5, 2025
8246317
wip: complete `top-level-interop.md`
lumirlumir Jun 5, 2025
a04b4c7
Merge branch 'main' into docs-create-dedicated-docs-for-json
lumirlumir Jun 5, 2025
b1d520b
Update docs/rules/no-duplicate-keys.md
lumirlumir Jun 7, 2025
d37c348
Update docs/rules/no-duplicate-keys.md
lumirlumir Jun 7, 2025
ba3bde9
Update docs/rules/no-duplicate-keys.md
lumirlumir Jun 7, 2025
702e7ec
Update docs/rules/no-duplicate-keys.md
lumirlumir Jun 7, 2025
6daff33
Update no-duplicate-keys.md
lumirlumir Jun 7, 2025
e86669e
Update docs/rules/no-empty-keys.md
lumirlumir Jun 7, 2025
c9c5dcf
Update docs/rules/no-unnormalized-keys.md
lumirlumir Jun 7, 2025
e1d4efb
Update docs/rules/no-unnormalized-keys.md
lumirlumir Jun 7, 2025
4dedb7b
Update docs/rules/no-unsafe-values.md
lumirlumir Jun 7, 2025
949bc16
Update docs/rules/sort-keys.md
lumirlumir Jun 7, 2025
81d1ea8
Update docs/rules/sort-keys.md
lumirlumir Jun 7, 2025
7f7d1c4
Update docs/rules/top-level-interop.md
lumirlumir Jun 7, 2025
120eca4
Update docs/rules/top-level-interop.md
lumirlumir Jun 7, 2025
ea09952
wip: formatting
lumirlumir Jun 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Overview

This package contains a plugin that allows you to natively lint JSON and JSONC files using ESLint.
This package contains a plugin that allows you to natively lint JSON, JSONC, and JSON5 files using ESLint.

**Important:** This plugin requires ESLint v9.6.0 or higher and you must be using the [new configuration system](https://eslint.org/docs/latest/use/configure/configuration-files).

Expand Down Expand Up @@ -31,12 +31,13 @@ deno add @eslint/json
This package exports these languages:

- `"json/json"` is for regular JSON files
- `"json/jsonc"` is for JSON files that support comments ([JSONC](https://github.com/microsoft/node-jsonc-parser)) such as those used for Visual Studio Code configuration files
- `"json/jsonc"` is for JSON files that support comments ([JSONC](https://github.com/microsoft/node-jsonc-parser)) such as those used for [Visual Studio Code](https://code.visualstudio.com/) configuration files
- `"json/json5"` is for [JSON5](https://json5.org) files

Depending on which types of JSON files you'd like to lint, you can set up your `eslint.config.js` file to include just the files you'd like. Here's an example that lints JSON, JSONC, and JSON5 files:

```js
// eslint.config.js
import { defineConfig } from "eslint/config";
import json from "@eslint/json";

Expand Down Expand Up @@ -79,6 +80,7 @@ export default defineConfig([
In CommonJS format:

```js
// eslint.config.js
const { defineConfig } = require("eslint/config");
const json = require("@eslint/json").default;

Expand Down Expand Up @@ -123,6 +125,7 @@ module.exports = defineConfig([
To use the recommended configuration for this plugin, specify your matching `files` and then use the `extends: ["json/recommended"]` property, like this:

```js
// eslint.config.js
import { defineConfig } from "eslint/config";
import json from "@eslint/json";

Expand Down Expand Up @@ -158,17 +161,17 @@ export default defineConfig([

## Rules

- `no-duplicate-keys` - warns when there are two keys in an object with the same text.
- `no-empty-keys` - warns when there is a key in an object that is an empty string or contains only whitespace (note: `package-lock.json` uses empty keys intentionally)
- `no-unsafe-values` - warns on values that are unsafe for interchange, such
- [`no-duplicate-keys`](./docs/rules/no-duplicate-keys.md) - warns when there are two keys in an object with the same text. (✅ recommended)
- [`no-empty-keys`](./docs/rules/no-empty-keys.md) - warns when there is a key in an object that is an empty string or contains only whitespace (note: `package-lock.json` uses empty keys intentionally) (✅ recommended)
- [`no-unsafe-values`](./docs/rules/no-unsafe-values.md) - warns on values that are unsafe for interchange, such
as strings with unmatched
[surrogates](https://en.wikipedia.org/wiki/UTF-16), numbers that evaluate to
Infinity, numbers that evaluate to zero unintentionally, numbers that look
like integers but are too large, and
[subnormal numbers](https://en.wikipedia.org/wiki/Subnormal_number).
- `no-unnormalized-keys` - warns on keys containing [unnormalized characters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize#description). You can optionally specify the normalization form via `{ form: "form_name" }`, where `form_name` can be any of `"NFC"`, `"NFD"`, `"NFKC"`, or `"NFKD"`.
- `sort-keys` - warns when keys are not in the specified order. Based on the ESLint [`sort-keys`](https://eslint.org/docs/latest/rules/sort-keys) rule.
- `top-level-interop` - warns when the top-level item in the document is neither an array nor an object. This can be enabled to ensure maximal interoperability with the oldest JSON parsers.
[subnormal numbers](https://en.wikipedia.org/wiki/Subnormal_number). (✅ recommended)
- [`no-unnormalized-keys`](./docs/rules/no-unnormalized-keys.md) - warns on keys containing [unnormalized characters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize#description). You can optionally specify the normalization form via `{ form: "form_name" }`, where `form_name` can be any of `"NFC"`, `"NFD"`, `"NFKC"`, or `"NFKD"`. (✅ recommended)
- [`sort-keys`](./docs/rules/sort-keys.md) - warns when keys are not in the specified order. Based on the ESLint [`sort-keys`](https://eslint.org/docs/latest/rules/sort-keys) rule.
- [`top-level-interop`](./docs/rules/top-level-interop.md) - warns when the top-level item in the document is neither an array nor an object. This can be enabled to ensure maximal interoperability with the oldest JSON parsers.

## Configuration Comments

Expand Down Expand Up @@ -205,6 +208,7 @@ Both line and block comments can be used for all kinds of configuration comments
The Microsoft implementation of JSONC optionally allows for trailing commas in objects and arrays (files like `tsconfig.json` have this option enabled by default in Visual Studio Code). To enable trailing commas in JSONC files, use the `allowTrailingCommas` language option, as in this example:

```js
// eslint.config.js
import { defineConfig } from "eslint/config";
import json from "@eslint/json";

Expand Down
81 changes: 81 additions & 0 deletions docs/rules/no-duplicate-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# no-duplicate-keys

Disallow duplicate keys in JSON objects.

## Background

The JSON specification doesn't explicitly forbid duplicate keys, but using them is considered a bad practice as it can lead to confusion and errors. Most parsers will only use the last occurrence of a duplicate key while others will throw an error. As such, it's considered a best practice to only have unique keys in JSON objects.

## Rule Details

This rule warns when there are two keys in an object with the same text, including when Unicode escape sequences resolve to the same character. For JSON5, this rule also considers identifier keys with the same text as string keys.

Examples of **incorrect** code for this rule:

```json5
/* eslint json/no-duplicate-keys: "error" */

{
"foo": 1,
"foo": 2
}

{
"foo": 1,
foo: 2 // Working with JSON5
}

{
"foo": {
"bar": 5
},
"foo": 6
}

// With Unicode escapes that resolve to the same key
{
"f\u006fot": 1,
"fo\u006ft": 2
}
```

Examples of **correct** code for this rule:

```jsonc
/* eslint json/no-duplicate-keys: "error" */

{
"foo": 1,
"bar": 2
}

{
"foo": 1,
"bar": 2,
"baz": 3
}

// Empty objects are valid
{}

// Nested objects with the same keys at different levels are valid
{
"foo": 1,
"bar": {
"bar": 2
}
}

{
"foo": {
"bar": 5
},
"bar": 6
}
```

## When Not to Use It

You might want to disable this rule in the rare case where you intentionally need to include duplicate keys in a JSON document for interoperability with systems that rely on this pattern. However, this is not recommended and usually indicates a design issue in the consuming application.

If you're working with non-standard JSON processors that have specific semantics for duplicate keys (such as using them for array-like constructs), you might need to disable this rule. However, consider using a more appropriate data structure or format for such cases.
74 changes: 74 additions & 0 deletions docs/rules/no-empty-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# no-empty-keys

Disallow empty keys in JSON objects.

## Background

In JSON, using empty keys (keys that are empty strings or contain only whitespace) can lead to accessibility and maintenance issues. While technically valid in JSON, empty keys make objects harder to read, can cause confusion when debugging, and may create problems with some JSON parsers or processors. Additionally, empty keys often indicate mistakes or oversights in the processes.

> [!NOTE]
>
> [`package-lock.json`](https://docs.npmjs.com/cli/configuring-npm/package-lock-json) uses empty keys intentionally.

## Rule Details

This rule warns when there is a key in an object that is an empty string or contains only whitespace.

Examples of **incorrect** code for this rule:

```jsonc
/* eslint json/no-empty-keys: "error" */

{
"": "value"
}

{
"validKey": "value",
"": "another value"
}

{
" ": "space as key"
}

{
"\t": "tab as key"
}

{
"\n": "newline as key"
}
```

Examples of **correct** code for this rule:

```jsonc
/* eslint json/no-empty-keys: "error" */

{
"key": "value"
}

{
"id": 1,
"name": "product"
}

// All keys must contain at least one non-whitespace character
{
"key1": "value1",
"key2": {
"nestedKey": "nested value"
}
}

// Empty objects are valid
{}
```

## When Not to Use It

You might want to disable this rule when working with specific JSON files that intentionally use empty keys as part of their schema or format. For example, as noted in the background, `package-lock.json` files sometimes use empty keys by design.

If you're working with JSON data from external systems that you cannot modify, and these systems use empty keys in their response format, you might need to disable this rule for those specific files.
97 changes: 97 additions & 0 deletions docs/rules/no-unnormalized-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# no-unnormalized-keys

Disallow JSON keys that are not normalized.

## Background

Unicode characters can sometimes have multiple representations that look identical but are technically different character sequences. For example, the character "é" can be represented as a single code point (U+00E9) or as an "e" followed by a combining accent (U+0065 + U+0301). This can lead to confusion, comparison issues, and unexpected behavior when working with JSON data.

Using normalized Unicode ensures consistent representation of text, which is important for key comparison, sorting, and searching operations. When keys are properly normalized, operations like key lookups and equality checks will work as expected across different systems and platforms.

## Rule Details

This rule checks that all object keys in your JSON are properly normalized according to Unicode normalization forms. By default, it uses the NFC normalization form, but you can optionally specify the normalization form via `{ form: "form_name" }`, where `form_name` can be any of `"NFC"`, `"NFD"`, `"NFKC"`, or `"NFKD"`.

Examples of **incorrect** code for this rule:

```jsonc
/* eslint json/no-unnormalized-keys: "error" */

// Key using decomposed form (NFD) instead of composed form (NFC)
{
"cafe\u0301": "value" // é as 'e' + combining accent
}

// Different representations of the same visual character
{
"cafè": "espresso",
"cafe\u0300": "latte" // same visual character in a different form
}
```

Examples of **correct** code for this rule:

```jsonc
/* eslint json/no-unnormalized-keys: "error" */

// Using NFC (default) normalized form
{
"café": "value" // é as a single code point
}

// All keys properly normalized
{
"résumé": "document",
"naïve": "approach",
"piñata": "party"
}

// ASCII-only keys are always normalized
{
"simple": "value",
"no_special_chars": true
}
```

## Options

The following options are available on this rule:

- `form: "NFC" | "NFD" | "NFKC" | "NFKD"` - specifies which Unicode normalization form to use when checking keys. Must be one of: `"NFC"` (default), `"NFD"`, `"NFKC"`, or `"NFKD"`.

Each normalization form has specific characteristics:

- **NFC**: Canonical Decomposition followed by Canonical Composition (default)
- **NFD**: Canonical Decomposition
- **NFKC**: Compatibility Decomposition followed by Canonical Composition
- **NFKD**: Compatibility Decomposition

Examples of **incorrect** code when configured as `"no-unnormalized-keys": ["error", { form: "NFD" }]`:

```jsonc
/* eslint json/no-unnormalized-keys: ["error", { form: "NFD" }] */

{
"café": "value", // é as a single code point is invalid in NFD
}
```

Examples of **correct** code when configured as `"no-unnormalized-keys": ["error", { form: "NFD" }]`:

```jsonc
/* eslint json/no-unnormalized-keys: ["error", { form: "NFD" }] */

{
"cafe\u0301": "value", // é represented as 'e' + combining accent is valid in NFD
}
```

## When Not to Use It

You might want to disable this rule if:

1. You're working with JSON data from external systems that you cannot modify, and normalizing the keys would break compatibility with those systems.
1. Your project specifically needs to maintain different Unicode representations for technical reasons.
1. Your JSON processing tools or environment have specific requirements regarding Unicode normalization that differ from the standard forms.

In most cases, however, following a consistent normalization form improves interoperability and prevents subtle bugs.
Loading