JSON Toolkit

Editor, Baris Arahan dan Rantaian Alat Automasi

Inti pati: Editor menyelesaikan "lihat dengan jelas, sunting dengan betul", manakala baris arahan menyelesaikan "kelompok, boleh diulang". Setiap pihak mempunyai beberapa alat yang kekal berguna selama satu dekad.

Pemula~10 min bacaanDiterbitkan 2026-10-30Dikemas kini 2026-10-30
Kulit Editor, baris arahan dan rantaian alat automasi

Kesimpulan utama: pilih editor mengikut senario — CodeMirror 6 untuk laman utiliti dan mudah alih, Monaco hanya apabila anda memerlukan pengalaman IDE penuh; serahkan kerja kelompok kepada jq ditambah tiga semakan CI untuk sintaks, struktur dan gaya, dan sentiasa hantar argumen dengan jq --arg.

Era memeriksa JSON dengan tangan sepatutnya sudah berakhir: apa sahaja yang boleh diulang oleh mesin, jangan serahkan kepada mata manusia.

1. Editor dalam pelayar

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 sebelum melakukan kerja berat; jangan format pada setiap ketukan kekunci
        scheduleParse(update.state.doc.toString());
      }
    }),
  ],
});

Empat perkara untuk diperhatikan:

  1. json() menyediakan penyerlahan sintaks dan padanan kurungan — jangan tulis sendiri;
  2. jsonParseLinter() menghasilkan penanda ralat pada peringkat baris/lajur; pasangkannya dengan lintGutter() untuk memaparkan ikon di sebelah nombor baris;
  3. updateListener mesti di-debounce; memanggil JSON.parse pada seratus ribu baris pada setiap ketukan kekunci akan kelihatan tersekat;
  4. Dokumen besar memerlukan pengoptimuman melebihi EditorView.lineWrapping untuk mengelakkan memaparkan keseluruhannya sekali gus (CodeMirror 6 memaparkan mengikut viewport secara lalai, yang merupakan peningkatan berbanding versi lama).

1.2 Lipatan dan rangka

CodeMirror 6 mempunyai lipatan terbina dalam; dalam senario JSON anda biasanya melipat mengikut "objek/tatasusunan":

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

Dengan foldGutter() dan keymap.of(foldKeymap), pengguna boleh meruntuhkan tatasusunan panjang dengan pintasan papan kekunci.

1.3 Memilih antara CodeMirror dan Monaco

Dimensi CodeMirror 6 Monaco
Saiz bundel Kecil, modular Besar (beberapa MB)
Mudah alih Disokong dengan baik Pengalaman sederhana
Perkhidmatan bahasa Mesti bina sendiri Kaya, terbina dalam
Kos penyesuaian Rendah Sederhana

Laman utiliti dan mudah alih dahulu → CodeMirror; pengalaman IDE penuh (berbilang fail, pergi ke definisi, penyempurnaan) → Monaco.

2. Baris arahan: enam resipi jq frekuensi tinggi

jq adalah kepada JSON seperti sed + awk kepada teks; mempelajari sebahagian kecil sintaksnya sahaja sudah meliputi lapan puluh peratus keperluan harian.

# 1. Pilih medan (paling biasa)
jq '.data.items[].name' response.json

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

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

# 4. Kumpul dan agregat
jq '[.items[]] | group_by(.category) | map({category: .[0].category, count: length})' response.json
# 5. Gabungkan berbilang fail menjadi tatasusunan
jq -s '.' part-*.json > merged.json

# 6. Proses JSON Lines baris demi baris
jq -c 'select(.level == "error")' app.jsonl

# Suis output biasa
jq -r '.data.name'      # Buang tanda petik supaya ia boleh disalurkan dengan bersih ke shell
jq -c '.'               # Output mampat, satu baris
jq --arg id "$ID" '.id == $id'   # Hantar argumen dengan selamat, mengelakkan suntikan melalui penggabungan

--arg patut disebut secara khas: menggabungkan pemboleh ubah terus ke dalam ungkapan akan rosak sebaik sahaja nilai mengandungi tanda petik, manakala --arg membiarkan jq mengendalikan pemisahan.

2.1 Alat lain secara sekilas

Alatan Tujuan Dalam satu ayat
yq Penukaran YAML/JSON/XML Sintaks serupa dengan jq, kuda kerja untuk fail konfigurasi
dasel Pertanyaan bersatu merentas format Menyokong JSON/YAML/TOML/XML/CSV
fx Pelayaran JSON interaktif Klik-klik dalam terminal, sesuai untuk penerokaan
jless Pelayaran berhalaman dalam terminal Seperti less, dengan lipatan dan carian
gron Ratakan JSON menjadi baris yang boleh digrep Alat hebat untuk mengetahui "medan ini berada di peringkat mana"
ajv-cli Pengesahan skema Sahkan fail JSON dalam CI

Idea di sebalik gron sangat patut 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 boleh mencari laluan, yang jauh lebih pantas daripada mengembangkan peringkat demi peringkat dalam editor.

3. Tiga lapisan pengesahan dalam CI

Lapisan Alatan Apa maksud kegagalan
Sintaks JSON.parse / jq empty Fail itu sendiri cacat
Struktur ajv-cli + skema Medan hilang, jenis salah
Gaya Prettier Pemformatan tidak konsisten, diff bising
# Sintaks: sahkan secara kelompok setiap fail json dalam repositori
find . -name '*.json' -not -path './node_modules/*' -print0 \
  | xargs -0 -n1 jq empty

# Struktur: sahkan terhadap skema
npx ajv-cli validate -s schemas/order.json -d 'fixtures/orders/*.json' --strict=false

# Gaya: semak sahaja, jangan ubah
npx prettier --check "**/*.json"

Anda memerlukan ketiga-tiga lapisan, kerana mesej ralatnya sama sekali berbeza: jq empty hanya menyatakan "baris mana yang rosak", ajv menyatakan "medan mana yang melanggar kata kunci mana", dan Prettier hanya menyatakan "pemformatan tidak konsisten".

4. Cangkuk pre-commit

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

Berhati-hati dengan fail konfigurasi alat seperti package.json dan tsconfig.json; jangan biarkan Prettier mengindentasi semula mereka secara semberono — sesetengah alat sensitif terhadap pemformatan (JSON yang sah sepatutnya tidak, tetapi dalam amalan ini telah menyebabkan masalah). Anda boleh mengecualikan mereka secara individu.

5. Petua penyahbugan

  1. Gunakan jq -e sebagai penegasan: kod keluar ialah 1 apabila hasil ungkapan false atau null, jadi ia boleh terus masuk ke dalam skrip sebagai semakan;
  2. jq 'paths' menyenaraikan semua laluan, memberikan anda gambaran pantas tentang struktur dokumen yang tidak dikenali;
  3. jq '.. | objects | keys' menemui setiap nama kunci yang pernah muncul, yang berguna untuk memburu ejaan yang tidak konsisten;
  4. Format sebelum membandingkan dalam editor: diff yang tidak diformat ialah bunyi tulen; perbandingan struktur seperti /diff lebih tepat.

6. Senarai semak

  • [ ] Penanda ralat editor tepat hingga baris dan lajur, dan penghuraian di-debounce;
  • [ ] Skrip pasukan menghantar argumen dengan jq --arg dan bukannya menggabungkan rentetan;
  • [ ] CI mempunyai ketiga-tiga lapisan pengesahan (sintaks/struktur/gaya);
  • [ ] pre-commit hanya memproses fail yang telah di-stage, supaya imbasan penuh tidak memperlahankan commit;
  • [ ] Versi alat dipasak dalam package.json atau .tool-versions.

Soalan Lazim

Bagaimana saya memilih antara CodeMirror 6 dan Monaco?

Untuk laman utiliti dan mudah alih, utamakan CodeMirror 6: ia kecil, modular dan disokong dengan baik pada mudah alih, serta penyerlahan sintaks, padanan kurungan dan lipatan boleh digubah mengikut keperluan. Gunakan Monaco hanya apabila anda memerlukan pengalaman IDE penuh dengan berbilang fail, pergi ke definisi dan penyempurnaan — dengan kos bundel beberapa megabait dan usaha penyesuaian yang lebih tinggi.

Mengapa CI memerlukan semakan sintaks, struktur dan gaya bersama-sama?

Ketiga-tiga lapisan melaporkan ralat yang sama sekali berbeza: jq empty menyatakan baris mana yang rosak, ajv menyatakan medan mana yang melanggar kata kunci mana, dan Prettier hanya menyatakan pemformatan tidak konsisten. Membuang satu lapisan menjadikan ralat lapisan lain mudah disalah tafsir, jadi kekalkan ketiga-tiganya dan berhenti sebaik sahaja satu lapisan gagal.

Patutkah saya bergantung pada pre-commit dan bukannya mengesahkan dalam CI?

Tidak. Cangkuk hanya memproses fail yang telah di-stage, yang memberikan maklum balas dalam satu minit tetapi tidak dapat meliputi keseluruhan repositori atau perubahan yang memintas commit. CI bertanggungjawab untuk kesempurnaan: kekalkan pre-commit pada fail yang di-stage dan serahkan imbasan penuh kepada CI.