JSON Toolkit

JSON5 dan JSONC: JSON dengan Komen

Inti pati: Kedua-dua dialek wujud kerana konfigurasi yang ditulis manusia memerlukan komen dan koma di hujung, tetapi sintaks dan jangkauan ekosistem mereka berbeza, jadi memilih yang salah menyekat rantaian alat anda.

Pemula~10 min bacaanDiterbitkan 2026-10-30Dikemas kini 2026-10-30
Kulit JSON5 dan JSONC, JSON dengan komen

Kesimpulan utama: gunakan JSONC untuk komen dalam konfigurasi VS Code dan TypeScript, gunakan JSON5 apabila anda memerlukan sintaks literal ES5.1 yang lebih luas seperti tanda petik tunggal atau kunci tanpa petik, dan kekalkan API awam pada JSON standard.

JSON standard tidak membenarkan komen, jadi setiap pasukan diam-diam tetap menulisnya — sehingga suatu hari binaan rosak. Daripada melakukannya secara rahsia, pilih dialek yang betul.

1. Kedua-dua dialek mempunyai motivasi berbeza

  • JSONC (JSON with Comments): JSON standard ditambah komen dan koma di hujung, dengan hampir tiada perubahan sintaks lain. Ia ialah standard de facto ekosistem VS Code — settings.json, tsconfig.json dan .eslintrc.json semuanya menggunakannya.
  • JSON5: jauh lebih bercita-cita tinggi, sejajar terus dengan literal objek ES5.1 — tanda petik tunggal, kunci tanpa petik, heksadesimal, Infinity/NaN, penerusan baris dengan garis songsang, dan tanda + di hadapan.

Satu ayat untuk membezakan mereka: JSONC hanya menjadikan penulisan selesa; JSON5 membolehkan anda menulis fail konfigurasi seolah-olah ia JavaScript.

2. Jadual perbandingan sintaks

Ciri JSON Standard JSONC JSON5
Komen // /* */ ✗ ✓ ✓
Koma di hujung ✗ ✓ ✓
Rentetan bertanda petik tunggal ✗ ✗ ✓
Kunci tanpa petik ✗ ✗ ✓
Nombor heksadesimal ✗ ✗ ✓
Titik perpuluhan di hadapan/belakang .5 5. ✗ ✗ ✓
Nombor bermula dengan + ✗ ✗ ✓
Infinity / NaN ✗ ✗ ✓
Penerusan \ di hujung baris ✗ ✗ ✓
Rentetan berbilang baris ✗ ✗ ✓ (dilaksanakan melalui penerusan)
Nilai peringkat atas sewenang-wenangnya ✓ ✓ ✓

Spesifikasi penuh JSON5 hampir tidak melebihi satu halaman; pakej json5 telah lama diselenggara oleh komuniti, dan pelayar serta Node berkelakuan sama.

3. Penghuraian: dua API, dua jenis keupayaan penentuan kedudukan

3.1 JSON5: penghuraian dokumen penuh yang ringkas

import JSON5 from 'json5';

const config = JSON5.parse(`
{
  // port perkhidmatan
  port: 8080,
  host: '0.0.0.0',
  features: ['json5', 'jsonc',],
  retries: 0x10,
}
`);

console.log(config.port, config.retries); // 8080 16

JSON5.parse mengembalikan objek biasa tanpa maklumat offset — kerana ia tidak disasarkan kepada senario penyuntingan, hanya kepada "membaca konfigurasi".

3.2 JSONC: pokok sintaks dengan offset

Nilai jsonc-parser bukan terletak pada penghuraian tetapi pada penyuntingan. Ia menawarkan tiga lapisan API:

API Tujuan Kegunaan tipikal
parse Huraikan menjadi pokok yang membawa offset/length Penyerlahan sintaks, lipatan, pelayaran
visit Laluan mendalam dahulu; panggil balik menerima laluan nod Pemeriksaan seperti JSONPath
modify + applyEdits Hasilkan suntingan teks minimum, kemudian gunakannya pada teks asal Ubah nilai sambil mengekalkan komen
import { parseTree, findNodeAtLocation, modify, applyEdits } from 'jsonc-parser';

const text = `{
  // konfigurasi port
  "server": {
    "port": 8080 // 80 dalam produksi
  }
}`;

const tree = parseTree(text);
const portNode = findNodeAtLocation(tree!, ['server', 'port']);
console.log(portNode?.offset, portNode?.length);

const edits = modify(text, ['server', 'port'], 3000, {
  formattingOptions: { insertSpaces: true, tabSize: 2 },
});
console.log(applyEdits(text, edits));

Output mengekalkan komen asal dan menggantikan hanya tiga aksara 8080:

{
  // konfigurasi port
  "server": {
    "port": 3000 // 80 dalam produksi
  }
}

Itulah tepat apa yang "menyunting konfigurasi dengan ungkapan nalar" tidak boleh lakukan: ungkapan nalar tidak tahu 8080 mana yang perlu diubah, dan tidak tahu bahawa 8080 di dalam rentetan mesti dibiarkan.

3.3 Mesej ralat mesti membawa offset

Kod ralat daripada jsonc-parser ialah nilai enum; yang biasa ialah:

Kod ralat Maksud
InvalidSymbol Aksara muncul yang sepatutnya tidak ada
PropertyNameExpected Menjangka nama kunci
ColonExpected Menjangka titik bertindih
CommaExpected Menjangka koma
CloseBraceExpected Objek tidak ditutup
UnexpectedEndOfComment Komen tidak ditutup
InvalidEscapeCharacter Escape tidak sah

Setelah offset ditukar menjadi baris dan lajur, editor boleh melukis goresan tepat pada kedudukan yang salah.

4. Bila hendak menggunakan yang mana

Senario Syor Sebab
Badan permintaan/respons API awam JSON standard Dialek tidak disokong oleh pelanggan serba guna
package.json, composer.json JSON standard Pengurus pakej hanya memahami JSON standard
tsconfig.json, .vscode/settings.json JSONC Lalai ekosistem, disokong secara asli oleh rantaian alat
Konfigurasi aplikasi (memerlukan komen) JSONC atau YAML Komen mesti dikekalkan manakala alat masih boleh membacanya
Memerlukan Infinity, heksadesimal, literal kompleks JSON5 Kuasa ekspresif paling kuat
Pertukaran data, log, cache JSON berdelimit baris atau standard Penstriman dan kesejagatan diperlukan

Peraturan praktikal: jika fail akan dibaca oleh "alat bukan manusia", utamakan JSON standard; pertimbangkan dialek hanya apabila anda pasti ia dibaca semata-mata oleh kod anda sendiri.

5. Tiga jenis risiko yang diperkenalkan dialek

5.1 Limpahan keperluan

Apabila alat lain membaca fail konfigurasi JSON5 dan memanggil JSON.parse, ia ranap terus. Gejala tipikal ialah "berfungsi baik secara setempat, gagal pada Docker" — kerana kontena menjalankan laluan bacaan yang berbeza.

Langkah balas: tambah semakan CI ke dalam repositori yang menyenaraikan secara eksplisit fail mana yang dibenarkan menggunakan dialek; semua yang lain disahkan sebagai JSON standard.

5.2 Kejutan sekitar inferens jenis

JSON5 membenarkan kunci tanpa petik dan tanda petik tunggal, tetapi ia tidak membenarkan anda membawa masuk binaan literal seperti tarikh atau ungkapan nalar — ia masih format data, bukan penilaian JavaScript. Orang pernah menganggap JSON5 boleh menyatakan new Date() hanya untuk melihat penghuraian gagal. JSON5 bukan eval.

5.3 Komen digugurkan secara senyap

Baik JSON5.stringify mahupun JSON.stringify tidak mengekalkan komen. Jadi "baca masuk, ubah sedikit nilai, tulis semula" menghilangkan setiap komen. Apabila komen mesti bertahan, satu-satunya pilihan ialah API penyuntingan jsonc-parser, atau pustaka YAML yang menyokong pengekalan komen.

6. Cadangan praktikal

  • [ ] Simpan jadual "jenis fail → format" dalam dokumentasi pasukan supaya tiada sesiapa membuat improvisasi;
  • [ ] Balut pembacaan konfigurasi dalam satu loadConfig() yang memutuskan secara dalaman penghurai mana untuk digunakan, supaya kod perniagaan tidak pernah memanggil JSON.parse secara terus;
  • [ ] Semasa mengubah konfigurasi dengan komen secara programatik, gunakan modify + applyEdits; jangan menulis semula keseluruhan fail;
  • [ ] Sahkan juga fail dialek dalam CI (jsonc-parser untuk JSONC, JSON5.parse untuk JSON5), jika tidak ralat sintaks hanya muncul pada masa jalan;
  • [ ] Gunakan JSON standard untuk antara muka awam, kunci cache dan muatan baris gilir mesej.

Soalan Lazim

Bagaimana saya harus memilih antara JSON5 dan JSONC?

Pilih mengikut masa jalan dan bukannya bilangan sintaks: VS Code, TypeScript dan ESLint membaca JSONC secara lalai, jadi JSONC memberikan keserasian terbaik; gunakan JSON5 hanya apabila anda memerlukan sintaks literal ES5.1 yang lebih luas, seperti tanda petik tunggal, kunci tanpa petik atau Infinity. Tiada dialek yang sesuai untuk respons API awam.

Mengapa penghurai JSON standard tidak boleh membaca JSONC secara terus?

JSONC membenarkan komen dan koma di hujung, manakala JSON.parse menerima hanya JSON RFC 8259 dan melontar pada kedua-duanya. Membaca JSONC memerlukan penghurai seperti jsonc-parser, atau membuang komen sebelum menyerahkan teks kepada penghurai standard.

Patutkah komen dalam JSONC bertahan selepas suntingan fail?

Ya, tetapi hanya melalui API penyuntingan. modify dan applyEdits dalam jsonc-parser mengubah nod sasaran sambil mengekalkan komen yang tinggal; menghuraikan kepada objek dan menyirikannya semula menggugurkan setiap komen.