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.

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:
json()menyediakan penyerlahan sintaks dan padanan kurungan — jangan tulis sendiri;jsonParseLinter()menghasilkan penanda ralat pada peringkat baris/lajur; pasangkannya denganlintGutter()untuk memaparkan ikon di sebelah nombor baris;updateListenermesti di-debounce; memanggilJSON.parsepada seratus ribu baris pada setiap ketukan kekunci akan kelihatan tersekat;- Dokumen besar memerlukan pengoptimuman melebihi
EditorView.lineWrappinguntuk 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
- Gunakan
jq -esebagai penegasan: kod keluar ialah 1 apabila hasil ungkapanfalseataunull, jadi ia boleh terus masuk ke dalam skrip sebagai semakan; jq 'paths'menyenaraikan semua laluan, memberikan anda gambaran pantas tentang struktur dokumen yang tidak dikenali;jq '.. | objects | keys'menemui setiap nama kunci yang pernah muncul, yang berguna untuk memburu ejaan yang tidak konsisten;- Format sebelum membandingkan dalam editor: diff yang tidak diformat ialah bunyi tulen; perbandingan struktur seperti
/difflebih tepat.
6. Senarai semak
- [ ] Penanda ralat editor tepat hingga baris dan lajur, dan penghuraian di-debounce;
- [ ] Skrip pasukan menghantar argumen dengan
jq --argdan 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.jsonatau.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.