JSON Toolkit

JSON5 dan JSONC: JSON dengan Komentar

Intinya: Kedua dialek ada karena konfigurasi yang ditulis manusia membutuhkan komentar dan koma di akhir, tetapi sintaks dan jangkauan ekosistemnya berbeda, sehingga pilihan yang salah membuat toolchain Anda macet.

Pemula±10 menit bacaDiterbitkan 2026-10-30Diperbarui 2026-10-30
Sampul artikel JSON5 dan JSONC, JSON dengan komentar

Intinya: gunakan JSONC untuk komentar di dalam konfigurasi VS Code dan TypeScript, gunakan JSON5 ketika Anda membutuhkan sintaks literal ES5.1 yang lebih luas seperti tanda kutip tunggal atau kunci tanpa tanda kutip, dan pertahankan API publik pada JSON standar.

JSON standar tidak mengizinkan komentar, sehingga setiap tim diam-diam tetap menulisnya — sampai suatu hari build rusak. Alih-alih melakukannya secara sembunyi-sembunyi, pilihlah dialek yang tepat.

1. Kedua dialek memiliki motivasi berbeda

  • JSONC (JSON with Comments): JSON standar plus komentar dan koma di akhir, hampir tanpa perubahan sintaks lain. Ia adalah standar de facto ekosistem VS Code — settings.json, tsconfig.json, dan .eslintrc.json semuanya menggunakannya.
  • JSON5: jauh lebih ambisius, selaras langsung dengan object literal ES5.1 — tanda kutip tunggal, kunci tanpa tanda kutip, heksadesimal, Infinity/NaN, kelanjutan baris dengan backslash, dan tanda + di depan.

Satu kalimat untuk membedakan keduanya: JSONC hanya membuat penulisan nyaman; JSON5 memungkinkan Anda menulis file konfigurasi seolah-olah itu JavaScript.

2. Tabel perbandingan sintaks

Fitur JSON standar JSONC JSON5
Komentar // /* */ ✗ ✓ ✓
Koma di akhir ✗ ✓ ✓
String dengan tanda kutip tunggal ✗ ✗ ✓
Kunci tanpa tanda kutip ✗ ✗ ✓
Angka heksadesimal ✗ ✗ ✓
Titik desimal di depan/di belakang .5 5. ✗ ✗ ✓
Angka yang dimulai dengan + ✗ ✗ ✓
Infinity / NaN ✗ ✗ ✓
Kelanjutan \ di akhir baris ✗ ✗ ✓
String multi-baris ✗ ✗ ✓ (diimplementasikan melalui kelanjutan)
Nilai tingkat atas apa pun ✓ ✓ ✓

Spesifikasi JSON5 lengkap tidak lebih dari satu halaman; paket json5 telah lama dipelihara oleh komunitas, dan peramban serta Node berperilaku identik.

3. Parsing: dua API, dua jenis kemampuan pelokasian

3.1 JSON5: parsing seluruh dokumen yang sederhana

import JSON5 from 'json5';

const config = JSON5.parse(`
{
  // service port
  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 informasi offset — karena ia tidak diarahkan ke skenario pengeditan, hanya ke "membaca konfigurasi".

3.2 JSONC: pohon sintaks dengan offset

Nilai jsonc-parser bukan pada parsing, melainkan pada pengeditan. Ia menawarkan tiga lapisan API:

API Tujuan Penggunaan tipikal
parse Mem-parse menjadi pohon yang membawa offset/length Penyorotan sintaks, folding, navigasi
visit Penelusuran depth-first; callback menerima path node Inspeksi mirip JSONPath
modify + applyEdits Menghasilkan edit teks minimal, lalu menerapkannya ke teks asli Mengubah nilai sambil mempertahankan komentar
import { parseTree, findNodeAtLocation, modify, applyEdits } from 'jsonc-parser';

const text = `{
  // port configuration
  "server": {
    "port": 8080 // 80 in production
  }
}`;

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 mempertahankan komentar asli dan hanya mengganti tiga karakter 8080:

{
  // port configuration
  "server": {
    "port": 3000 // 80 in production
  }
}

Itulah tepatnya yang tidak dapat dilakukan oleh "mengedit konfigurasi dengan ekspresi reguler": regex tidak tahu 8080 mana yang harus diubah, dan tidak tahu bahwa 8080 di dalam string harus dibiarkan.

3.3 Pesan error harus membawa offset

Kode error dari jsonc-parser adalah nilai enum; yang umum adalah:

Kode error Makna
InvalidSymbol Muncul karakter yang seharusnya tidak ada
PropertyNameExpected Diharapkan nama kunci
ColonExpected Diharapkan titik dua
CommaExpected Diharapkan koma
CloseBraceExpected Objek tidak ditutup
UnexpectedEndOfComment Komentar tidak ditutup
InvalidEscapeCharacter Escape tidak valid

Setelah offset dikonversi menjadi baris dan kolom, editor dapat menggambar garis bergelombang tepat pada posisi yang bermasalah.

4. Kapan menggunakan yang mana

Skenario Rekomendasi Alasan
Body request/response API publik JSON standar Dialek tidak didukung klien serbaguna
package.json, composer.json JSON standar Manajer paket hanya memahami JSON standar
tsconfig.json, .vscode/settings.json JSONC Bawaan ekosistem, didukung native oleh toolchain
Konfigurasi aplikasi (butuh komentar) JSONC atau YAML Komentar harus dipertahankan sementara alat masih dapat membaca dan menulisnya
Membutuhkan Infinity, heksadesimal, literal kompleks JSON5 Daya ekspresi terkuat
Pertukaran data, log, cache JSON per baris atau standar Streaming dan universalitas diperlukan

Aturan praktis: jika file akan dibaca oleh "alat non-manusia", utamakan JSON standar; pertimbangkan dialek hanya ketika Anda yakin file itu hanya dibaca oleh kode Anda sendiri.

5. Tiga jenis risiko yang diperkenalkan dialek

5.1 Kebutuhan yang merembes keluar

Ketika alat lain membaca file konfigurasi JSON5 dan memanggil JSON.parse, ia crash langsung. Gejala tipikalnya adalah "berfungsi baik secara lokal, gagal di Docker" — karena container menjalankan jalur pembacaan yang berbeda.

Penanggulangan: tambahkan pemeriksaan CI ke repositori yang secara eksplisit mencantumkan file mana yang diizinkan menggunakan dialek; sisanya divalidasi sebagai JSON standar.

5.2 Kejutan seputar inferensi tipe

JSON5 mengizinkan kunci tanpa tanda kutip dan tanda kutip tunggal, tetapi ia tidak membiarkan Anda memasukkan konstruksi literal seperti tanggal atau ekspresi reguler — ia tetap format data, bukan evaluasi JavaScript. Orang pernah menganggap JSON5 dapat mengekspresikan new Date() hanya untuk melihat parsing gagal. JSON5 bukan eval.

5.3 Komentar hilang secara diam-diam

Baik JSON5.stringify maupun JSON.stringify tidak mempertahankan komentar. Jadi "baca, ubah sebuah nilai, tulis kembali" kehilangan setiap komentar. Ketika komentar harus bertahan, satu-satunya opsi adalah API pengeditan jsonc-parser, atau pustaka YAML yang mendukung pelestarian komentar.

6. Rekomendasi praktis

  • [ ] Pertahankan tabel "jenis file → format" dalam dokumentasi tim agar tidak ada yang berimprovisasi;
  • [ ] Bungkus pembacaan konfigurasi dalam satu loadConfig() yang memutuskan secara internal parser mana yang dipakai, sehingga kode bisnis tidak pernah memanggil JSON.parse secara langsung;
  • [ ] Saat mengubah konfigurasi berkomentar secara programatik, gunakan modify + applyEdits; jangan pernah menulis ulang seluruh file;
  • [ ] Validasi juga file dialek di CI (jsonc-parser untuk JSONC, JSON5.parse untuk JSON5), jika tidak error sintaks hanya muncul saat runtime;
  • [ ] Gunakan JSON standar untuk antarmuka publik, kunci cache, dan payload message queue.

FAQ

Bagaimana cara memilih antara JSON5 dan JSONC?

Pilih berdasarkan runtime, bukan berdasarkan jumlah sintaks: VS Code, TypeScript dan ESLint membaca JSONC secara bawaan, sehingga JSONC memberi kompatibilitas terbaik; gunakan JSON5 hanya ketika Anda membutuhkan sintaks literal ES5.1 yang lebih luas, seperti tanda kutip tunggal, kunci tanpa tanda kutip, atau Infinity. Tidak ada dialek yang cocok untuk respons API publik.

Mengapa parser JSON standar tidak dapat membaca JSONC secara langsung?

JSONC mengizinkan komentar dan koma di akhir, sementara JSON.parse hanya menerima JSON RFC 8259 dan melempar error pada keduanya. Membaca JSONC memerlukan parser seperti jsonc-parser, atau menghapus komentar sebelum menyerahkan teks kepada parser standar.

Apakah komentar di JSONC tetap bertahan saat file diedit?

Ya, tetapi hanya melalui API pengeditan. modify dan applyEdits di jsonc-parser mengubah node target sambil mempertahankan komentar yang tersisa; mem-parse menjadi objek lalu men-stringify-nya menghilangkan setiap komentar.