JSON Toolkit

Editor, Command Line, dan Toolchain Otomasi

Intinya: Editor memecahkan masalah "lihat dengan jelas, edit dengan benar", sementara command line memecahkan "batch, dapat diulang". Masing-masing punya beberapa alat yang tetap berguna selama satu dekade.

Pemula±10 menit bacaDiterbitkan 2026-10-30Diperbarui 2026-10-30
Sampul artikel editor, command line, dan toolchain otomasi

Intinya: pilih editor berdasarkan skenario — CodeMirror 6 untuk situs utilitas dan mobile, Monaco hanya ketika Anda membutuhkan pengalaman IDE lengkap; serahkan pekerjaan batch kepada jq plus tiga pemeriksaan CI untuk sintaks, struktur, dan gaya, dan selalu teruskan argumen dengan jq --arg.

Era memeriksa JSON dengan tangan seharusnya sudah berakhir: apa pun yang dapat diulang oleh mesin, jangan serahkan kepada mata manusia.

1. Editor di peramban

1.1 Integrasi CodeMirror 6 minimal

import { EditorView, basicSetup } from 'codemirror';
import { json, jsonParseLinter } from '@codemirror/lang-json';
import { linter, lintGutter } from '@codemirror/lint';

const view = new EditorView({
  parent: document.getElementById('editor')!,
  doc: '{"hello": "json"}',
  extensions: [
    basicSetup,
    json(),
    linter(jsonParseLinter()),
    lintGutter(),
    EditorView.updateListener.of((update) => {
      if (update.docChanged) {
        // Debounce before doing heavy work; do not format on every keystroke
        scheduleParse(update.state.doc.toString());
      }
    }),
  ],
});

Empat hal yang perlu diperhatikan:

  1. json() menyediakan penyorotan sintaks dan pencocokan kurung — jangan menulis sendiri;
  2. jsonParseLinter() menghasilkan penanda error tingkat baris/kolom; pasangkan dengan lintGutter() untuk menampilkan ikon di samping nomor baris;
  3. updateListener harus di-debounce; memanggil JSON.parse pada seratus ribu baris di setiap ketukan tombol akan terasa lambat;
  4. Dokumen besar membutuhkan optimasi di luar EditorView.lineWrapping agar tidak merender seluruhnya sekaligus (CodeMirror 6 merender berdasarkan viewport secara bawaan, yang merupakan peningkatan dibanding versi lama).

1.2 Folding dan outline

CodeMirror 6 memiliki folding bawaan; dalam skenario JSON Anda biasanya melipat berdasarkan "objek/array":

import { foldGutter, foldKeymap } from '@codemirror/language';
import { keymap } from '@codemirror/view';

Dengan foldGutter() dan keymap.of(foldKeymap), pengguna dapat melipat array panjang dengan pintasan keyboard.

1.3 Memilih antara CodeMirror dan Monaco

Dimensi CodeMirror 6 Monaco
Ukuran bundle Kecil, modular Besar (beberapa MB)
Mobile Didukung dengan baik Pengalaman biasa saja
Layanan bahasa Harus dibuat sendiri Kaya, sudah bawaan
Biaya kustomisasi Rendah Sedang

Situs utilitas dan mobile-first → CodeMirror; pengalaman IDE lengkap (banyak file, go-to-definition, penyelesaian kode) → Monaco.

2. Command line: enam resep jq yang sering dipakai

jq bagi JSON seperti sed + awk bagi teks; mempelajari sedikit saja sintaksnya sudah mencakup delapan puluh persen kebutuhan sehari-hari.

# 1. Pick fields (the most common)
jq '.data.items[].name' response.json

# 2. Filter + reshape
jq '.data.items[] | select(.price < 10) | {id, price}' response.json

# 3. Aggregates (length, sum, max)
jq '[.items[] | .price] | {count: length, total: add, max: max}' response.json

# 4. Group and aggregate
jq '[.items[]] | group_by(.category) | map({category: .[0].category, count: length})' response.json
# 5. Merge multiple files into an array
jq -s '.' part-*.json > merged.json

# 6. Process JSON Lines line by line
jq -c 'select(.level == "error")' app.jsonl

# Common output switches
jq -r '.data.name'      # Strip the quotes so it pipes cleanly into the shell
jq -c '.'               # Compact output, one line
jq --arg id "$ID" '.id == $id'   # Pass arguments safely, avoiding injection through concatenation

--arg layak mendapat perhatian khusus: menggabungkan variabel langsung ke dalam ekspresi akan rusak begitu nilainya mengandung tanda kutip, sedangkan --arg membiarkan jq menangani escaping-nya.

2.1 Alat lain sekilas

Alat Tujuan Dalam satu kalimat
yq Konversi YAML/JSON/XML Sintaks mirip jq, andalan untuk file konfigurasi
dasel Kueri terpadu lintas format Mendukung JSON/YAML/TOML/XML/CSV
fx Penjelajahan JSON interaktif Klik-klik di terminal, bagus untuk eksplorasi
jless Penjelajahan berhalaman di terminal Seperti less, dengan folding dan pencarian
gron Meratakan JSON menjadi baris yang bisa di-grep Alat hebat untuk mencari tahu "field ini ada di level mana"
ajv-cli Validasi Schema Memvalidasi file JSON di CI

Gagasan di balik gron sangat layak diketahui:

$ echo '{"a":{"b":[1,2]}}' | gron
json = {};
json.a = {};
json.a.b = [];
json.a.b[0] = 1;
json.a.b[1] = 2;

Setelah diratakan, grep dapat menemukan path, yang jauh lebih cepat daripada memperluas level demi level di editor.

3. Tiga lapisan validasi di CI

Lapisan Alat Arti kegagalan
Sintaks JSON.parse / jq empty File itu sendiri cacat
Struktur ajv-cli + schema Field hilang, tipe salah
Gaya Prettier Format tidak konsisten, diff berisik
# Syntax: batch-validate every json file in the repository
find . -name '*.json' -not -path './node_modules/*' -print0 \
  | xargs -0 -n1 jq empty

# Structure: validate against a schema
npx ajv-cli validate -s schemas/order.json -d 'fixtures/orders/*.json' --strict=false

# Style: check only, do not modify
npx prettier --check "**/*.json"

Anda membutuhkan ketiga lapisan, karena pesan errornya sepenuhnya berbeda: jq empty hanya mengatakan "baris mana yang rusak", ajv mengatakan "field mana yang melanggar kata kunci mana", dan Prettier hanya mengatakan "formatnya tidak konsisten".

4. Hook pre-commit

# .husky/pre-commit example (excerpt)
npx lint-staged
{
  "lint-staged": {
    "*.json": ["prettier --write", "jq empty"]
  }
}

Hati-hati dengan file konfigurasi alat seperti package.json dan tsconfig.json; jangan biarkan Prettier mengubah indentasinya begitu saja — sebagian alat sensitif terhadap format (JSON yang valid seharusnya tidak, tetapi dalam praktiknya hal ini pernah menimbulkan masalah). Anda dapat mengecualikannya satu per satu.

5. Tips debugging

  1. Gunakan jq -e sebagai asersi: exit code bernilai 1 ketika hasil ekspresi false atau null, sehingga dapat langsung dipakai di skrip sebagai pemeriksaan;
  2. jq 'paths' mencantumkan semua path, memberi Anda gambaran cepat tentang struktur dokumen yang asing;
  3. jq '.. | objects | keys' menemukan setiap nama kunci yang pernah muncul, berguna untuk memburu penulisan yang tidak konsisten;
  4. Format dulu sebelum membandingkan di editor: diff yang tidak diformat adalah kebisingan murni; perbandingan struktural seperti /diff lebih akurat.

6. Checklist

  • [ ] Penanda error editor presisi hingga baris dan kolom, dan parsing di-debounce;
  • [ ] Skrip tim meneruskan argumen dengan jq --arg alih-alih menggabungkan string;
  • [ ] CI memiliki ketiga lapisan validasi (sintaks/struktur/gaya);
  • [ ] pre-commit hanya memproses file yang di-stage, agar pemindaian penuh tidak memperlambat commit;
  • [ ] Versi alat dipatok di package.json atau .tool-versions.

FAQ

Bagaimana memilih antara CodeMirror 6 dan Monaco?

Untuk situs utilitas dan mobile, pilih CodeMirror 6: ukurannya kecil, modular, dan didukung baik di mobile, serta penyorotan sintaks, pencocokan kurung, dan folding dapat disusun sesuai kebutuhan. Gunakan Monaco hanya ketika Anda membutuhkan pengalaman IDE lengkap dengan banyak file, go-to-definition, dan penyelesaian kode — dengan konsekuensi bundle beberapa megabyte dan usaha kustomisasi lebih tinggi.

Mengapa CI membutuhkan pemeriksaan sintaks, struktur, dan gaya sekaligus?

Ketiga lapisan melaporkan error yang sepenuhnya berbeda: jq empty mengatakan baris mana yang rusak, ajv mengatakan field mana yang melanggar kata kunci mana, dan Prettier hanya mengatakan formatnya tidak konsisten. Menghilangkan satu lapisan membuat error lapisan lain mudah disalahpahami, jadi pertahankan ketiganya dan hentikan segera setelah satu lapisan gagal.

Haruskah saya mengandalkan pre-commit alih-alih memvalidasi di CI?

Tidak. Hook hanya memproses file yang di-stage, yang memberi umpan balik dalam satu menit tetapi tidak dapat mencakup seluruh repositori atau perubahan yang melewati commit. CI bertanggung jawab atas kelengkapan: biarkan pre-commit menangani file yang di-stage dan serahkan pemindaian penuh kepada CI.