Editor, riga di comando e toolchain di automazione
In sintesi: Gli editor risolvono "vederlo chiaramente, modificarlo correttamente", mentre la riga di comando risolve "in batch, ripetibile". Su entrambi i fronti ci sono pochi strumenti che restano utili per un decennio.

In sintesi: scegli l'editor in base allo scenario — CodeMirror 6 per i siti di utilità e il mobile, Monaco solo quando ti serve l'esperienza completa di un IDE; lascia il lavoro in batch a jq più tre controlli in CI per sintassi, struttura e stile, e passa sempre gli argomenti con jq --arg.
L'epoca di controllare il JSON a mano dovrebbe essere finita: tutto ciò che una macchina può ripetere, non lasciarlo agli occhi umani.
1. Editor nel browser
1.1 Integrazione minima di CodeMirror 6
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());
}
}),
],
});
Quattro punti da notare:
json()fornisce evidenziazione della sintassi e abbinamento delle parentesi — non scriverlo da te;jsonParseLinter()produce marker di errore a livello di riga e colonna; abbinalo alintGutter()per mostrare le icone accanto ai numeri di riga;- Il
updateListenerdeve essere sottoposto a debounce; chiamareJSON.parsesu centomila righe a ogni tasto premuto causerà un lag evidente; - I documenti grandi richiedono ottimizzazioni oltre a
EditorView.lineWrappingper evitare di renderizzare tutto in una volta (CodeMirror 6 renderizza per viewport per impostazione predefinita, un miglioramento rispetto alle versioni precedenti).
1.2 Folding e outline
CodeMirror 6 ha il folding integrato; negli scenari JSON di solito si piega per "oggetto/array":
import { foldGutter, foldKeymap } from '@codemirror/language';
import { keymap } from '@codemirror/view';
Con foldGutter() e keymap.of(foldKeymap), gli utenti possono comprimere gli array lunghi con una scorciatoia da tastiera.
1.3 Scegliere tra CodeMirror e Monaco
| Dimensione | CodeMirror 6 | Monaco |
|---|---|---|
| Dimensione del bundle | Piccola, modulare | Grande (diversi MB) |
| Mobile | Ben supportato | Esperienza mediocre |
| Servizi linguistici | Bisogna costruirli | Ricchi, integrati |
| Costo di personalizzazione | Basso | Medio |
Siti di utilità e mobile-first → CodeMirror; esperienza completa di IDE (più file, go-to-definition, completamento) → Monaco.
2. Riga di comando: sei ricette jq ad alta frequenza
jq è per JSON ciò che sed + awk sono per il testo; imparare solo una piccola parte della sua sintassi copre l'ottanta per cento delle esigenze quotidiane.
# 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 merita una menzione speciale: concatenare direttamente una variabile in un'espressione si rompe non appena il valore contiene virgolette, mentre con --arg è jq a gestire l'escape.
2.1 Altri strumenti in sintesi
| Strumento | Scopo | In una frase |
|---|---|---|
yq |
Conversione YAML/JSON/XML | Sintassi simile a jq, il cavallo di battaglia dei file di configurazione |
dasel |
Query unificata tra formati | Supporta JSON/YAML/TOML/XML/CSV |
fx |
Navigazione interattiva di JSON | Clicca nel terminale, utile per esplorare |
jless |
Navigazione paginata nel terminale | Come less, con folding e ricerca |
gron |
Appiattisce JSON in righe cercabili con grep | Uno strumento fantastico per capire "a quale livello sta questo campo" |
ajv-cli |
Validazione dello schema | Valida i file JSON in CI |
L'idea dietro gron vale la pena di essere conosciuta:
$ echo '{"a":{"b":[1,2]}}' | gron
json = {};
json.a = {};
json.a.b = [];
json.a.b[0] = 1;
json.a.b[1] = 2;
Una volta appiattito, grep può localizzare il percorso, molto più veloce che espandere livello per livello in un editor.
3. Tre livelli di validazione in CI
| Livello | Strumento | Cosa significa un errore |
|---|---|---|
| Sintassi | JSON.parse / jq empty |
Il file stesso è malformato |
| Struttura | ajv-cli + schema |
Campi mancanti, tipi errati |
| Stile | Prettier | Formattazione incoerente, diff rumorosi |
# 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"
Servono tutti e tre i livelli, perché i loro messaggi di errore sono completamente diversi:
jq empty dice solo "quale riga è rotta", ajv dice "quale campo viola quale parola chiave", e Prettier dice solo "la formattazione è incoerente".
4. Hook pre-commit
# .husky/pre-commit example (excerpt)
npx lint-staged
{
"lint-staged": {
"*.json": ["prettier --write", "jq empty"]
}
}
Attenzione ai file di configurazione degli strumenti come package.json e tsconfig.json; non lasciare che Prettier li rientri casualmente —
alcuni strumenti sono sensibili alla formattazione (il JSON valido non dovrebbe esserlo, ma in pratica ha causato problemi). Puoi escluderli singolarmente.
5. Suggerimenti di debug
- Usa
jq -ecome asserzione: il codice di uscita è 1 quando il risultato dell'espressione èfalseonull, quindi può entrare direttamente negli script come controllo; jq 'paths'elenca tutti i percorsi, dandoti una rapida panoramica della struttura di un documento che non conosci;jq '.. | objects | keys'trova ogni nome di chiave mai comparso, utile per scovare grafie incoerenti;- Formatta prima di confrontare nell'editor: un diff non formattato è puro rumore; un confronto strutturale come
/diffè più accurato.
6. Checklist
- [ ] I marker di errore dell'editor sono precisi a riga e colonna, e il parsing è sottoposto a debounce;
- [ ] Gli script del team passano gli argomenti con
jq --arginvece di concatenare stringhe; - [ ] La CI ha tutti e tre i livelli di validazione (sintassi/struttura/stile);
- [ ] Il pre-commit elabora solo i file in staging, così una scansione completa non rallenta i commit;
- [ ] Le versioni degli strumenti sono fissate in
package.jsono.tool-versions.
FAQ
Come scelgo tra CodeMirror 6 e Monaco?
Per i siti di utilità e il mobile, preferisci CodeMirror 6: è piccolo, modulare e ben supportato sul mobile, e evidenziazione della sintassi, abbinamento delle parentesi e folding si possono comporre secondo necessità. Ricorri a Monaco solo quando ti serve l'esperienza completa di IDE con più file, go-to-definition e completamento — al costo di un bundle di diversi megabyte e di uno sforzo di personalizzazione maggiore.
Perché la CI ha bisogno insieme di controlli di sintassi, struttura e stile?
I tre livelli riportano errori completamente diversi: jq empty dice quale riga è rotta, ajv dice quale campo viola quale parola chiave, e Prettier dice solo che la formattazione è incoerente. Togliere un livello rende gli errori degli altri facili da fraintendere, quindi tieni tutti e tre e fermati non appena un livello fallisce.
Devo affidarmi al pre-commit invece di validare in CI?
No. Gli hook elaborano solo i file in staging, il che dà feedback entro un minuto ma non può coprire l'intero repository o le modifiche che aggirano il commit. La CI è responsabile della completezza: mantieni il pre-commit sui file in staging e lascia le scansioni complete alla CI.