io costruisco Toolz.dev, e prima di allora ho passato anni a spedire plugin WordPress e API Laravel In tutto, il singolo messaggio di errore su cui ho perso più ore è una qualche variazione di & quot; Token imprevisto in JSON alla posizione 428.& quot; non ti dice quasi nulla Non c'è nessuna riga, nessuna colonna e la posizione che nomina è spesso qualche carattere oltre la cosa che non va Finisci per contare i caratteri in un blob minificato a mano, o incollare l'intero payload in un editor e strizzare gli occhi Ho costruito il Convalidatore JSON quindi non devo mai più farlo, e questa è la guida a cosa fa e perché convalidare JSON è più complicato di quanto sembri.
tl; dr: Un validatore JSON controlla il testo rispetto alla grammatica in RFC 8259 e, quando il testo è rotto, ti dice la linea esatta, la colonna e il carattere del primo errore, formulato in termini di ciò che si aspettava Inoltre cattura le cose che un normale parser nasconde: chiavi duplicate, che vengono silenziosamente collassate all'ultimo valore, e riporta la struttura di un documento valido (oggetto, array e conteggi di chiavi, profondità di annidamento e dimensione dei byte) Non è un formattatore Un formattatore presuppone che l'input sia già valido; un validatore è la cosa che raggiungi proprio quando non lo è.
Cosa significa per JSON essere valido?
JSON è un piccolo formato con una grammatica rigorosa Lo standard attuale è RFC 8259, con cui allinearsi ECMA-404, e tra di loro definiscono esattamente ciò che un documento valido può contenere Un testo JSON è un singolo valore Quel valore è un oggetto, un array, una stringa, un numero, true, false, o null. Gli oggetti sono avvolti in parentesi graffe e tengono separati da virgole "key": value coppie Gli array sono avvolti in parentesi e contengono valori separati da virgole Le stringhe sono avvolte in virgolette doppie, mai virgolette singole I numeri seguono una forma specifica senza zeri iniziali e senza virgola finale Non ci sono commenti e non ci sono virgole finali.
Quell'ultima frase è dove la maggior parte del JSON del mondo reale va storto, perché molte persone JSON scrivono a mano non è realmente JSON. È un file di configurazione con // commenti, o un oggetto copiato da un'origine JavaScript in cui le virgolette singole e le virgolette finali vanno bene, o un dispositivo modificato a mano in cui qualcuno ha aggiunto un campo e lasciato una virgola penzolante. Tutti questi vengono rifiutati da un parser rigoroso e da un validator' il suo compito è rifiutarli in un punto specifico anziché con un'alzata di spalle.
Un punto che vale la pena chiarire, perché fa inciampare le persone che hanno imparato JSON anni fa: un valore semplice è un documento JSON completo e valido. 42 da solo è valido JSON. Così è "hello", e lo è anche true. Il vecchio RFC4627 richiesto il livello superiore per essere un oggetto o un array, ma tale restrizione è stata abbandonata nel 2014 quando RFC 7159 (successivamente 8259) lo ha sostituito Se uno strumento ti dice 42 non è valido JSON, quello strumento sta seguendo una specifica che è obsoleta da oltre un decennio.
Perché JSON.parse è un reporter di errori così grave?
Il motivo per cui un validatore dedicato guadagna il suo posto è che il parser integrato nella tua lingua è ottimizzato per il percorso felice, non per spiegare quello triste. JSON.parse in un browser si lancia un SyntaxError il cui messaggio è specifico del motore e di solito ti dà un offset di caratteri senza riga o colonna V8 dice & quot; Token imprevisto } in JSON alla posizione 148.& quot; Firefox dice & quot; JSON.parse: carattere inaspettato alla riga 1 colonna 149.& quot; Safari dice di nuovo qualcosa di diverso Nessuno di loro ti dice cosa si aspettavano e la posizione viene misurata dall'inizio della stringa, il che è inutile nel momento in cui il tuo JSON ha più di un paio di righe.
Il validatore su Toolz.dev non utilizza JSON.parse. Cammina il testo stesso con un parser a discesa ricorsiva scritto a mano, tracciando la linea e la colonna mentre procede, quindi quando si ferma può darti tutte e tre le coordinate: la linea, la colonna e l'offset assoluto del carattere Più importante, conosce la regola grammaticale in cui si trovava nel mezzo, quindi il messaggio è specifico Invece di & quot; token imprevisto, & quot; ottieni & quot; La virgola trainante non è consentita prima della parentesi graffa di chiusura, & quot; o & quot; Le chiavi oggetto devono essere stringhe a doppia citazione, & quot; o & quot; Si prevede una virgola o una parentesi graffa di chiusura dopo un membro dell'oggetto.& quot; Questa differenza è la differenza tra fissare il file in cinque secondi e cercarlo.
Disegna anche un caret sotto il carattere esatto sulla riga incriminata, come fa un compilatore Quando stai guardando la riga 34 di un file di configurazione, & quot; colonna 12" va bene, ma a ^ sedersi direttamente sotto la citazione vagante è più veloce.
Quali errori JSON cattura il validatore per nome?
Questi sono i fallimenti che vedo più spesso, sia nel mio lavoro che nei thread di supporto per strumenti come questo Il validatore nomina ciascuno piuttosto che segnalare un errore generico del token.
| Errore | Come appare | Perché non è valido |
|---|---|---|
| Trailing comma | {"a": 1,} oppure [1, 2,] |
JSON non ha virgole finali; la grammatica standard' semplicemente non ne consente una prima di una parentesi graffa o parentesi di chiusura |
| Citazioni singole | {'name': 'Liton'} |
Le stringhe e i tasti devono utilizzare virgolette doppie; le virgolette singole sono un'abitudine JavaScript, non JSON |
| Comma mancante | {"a": 1 "b": 2} |
Ogni membro dopo il primo deve essere preceduto da una virgola |
| commentario | {"a": 1} // note |
JSON non ha sintassi di commento; IL // e tutto dopo è contenuto inaspettato |
| Chiave non citata | {name: "Liton"} |
Le chiavi sono stringhe e devono essere quotate, a differenza dei letterali degli oggetti JavaScript |
| Leading zero | {"n": 007} |
Un numero potrebbe non avere uno zero iniziale, quindi 007 non è valido; scrivere 7 |
| Punto decimale finale | {"n": 5.} |
La frazione dopo un punto decimale necessita di almeno una cifra |
| Carattere di controllo grezzo | una scheda letterale o una nuova riga all'interno di una stringa | I caratteri di controllo all'interno delle stringhe devono essere sfuggiti come \t, \n, e così via |
| NaN o Infinito | {"n": NaN} |
Questi sono validi in JavaScript ma non sono valori JSON |
| Stringa non terminata | {"a": "oops} |
Una stringa senza virgolette di chiusura viene eseguita fino alla fine dell'input |
Ognuno di questi produce un messaggio in linguaggio semplice e una posizione Il caso iniziale-zero è un bell'esempio del perché un parser appositamente costruito aiuta: si legge in un parser generico 007 come il numero 0 e poi inciampa nel 7 come & quot; contenuto extra, & quot; puntandoti verso il 7, quando il vero problema sono i due zeri davanti ad esso Il validatore controlla prima il modello iniziale-zero e te lo dice direttamente.
E le chiavi duplicate?
Ecco quello che mi ha morso in produzione più di ogni errore di sintassi, perché non è affatto un errore di sintassi Questo è valido JSON:
{
"timeout": 30,
"retries": 3,
"timeout": 60
}
RFC 8259 dice che i nomi all'interno di un oggetto & quot; DOVREBBE essere univoco, & quot; ma non vieta i duplicati, quindi è necessario un parser per accettarlo Ciò che accade dopo è dove inizia il problema: lo standard dice che il comportamento con i nomi duplicati è imprevedibile, e in pratica quasi ogni parser mantiene l'ultimo valore e scarta silenziosamente quelli precedenti. Quindi questo oggetto si analizza {"timeout": 60, "retries": 3}, e il "timeout": 30 hai impostato con attenzione nella parte superiore del file è andato senza un avviso Se due persone hanno modificato la configurazione, o una fusione è andata storta, o un passo di template ha emesso la stessa chiave due volte, hai un bug che nessun parser mai contrassegnare per voi.
Il validatore lo segnala Il rilevamento della chiave duplicata è attivo per impostazione predefinita e, poiché un duplicato è legale, viene segnalato come un avviso anziché come un errore: il documento è ancora valido, ma ti viene comunicata ogni chiave che appare più di una volta nello stesso oggetto, con la sua riga e un Puntatore JSON percorso in modo da poterlo trovare all'interno di una struttura nidificata. Se desideri veramente duplicati, puoi disattivare il controllo. La maggior parte delle volte, vedere l'avviso è il momento in cui ti rendi conto di cosa è andato storto.
In cosa è diverso un validatore da un formattatore?
Le persone usano le parole in modo intercambiabile e gli strumenti si sovrappongono, ma rispondono a domande diverse. UN Formattatore JSON prende JSON che già credi sia valido e lo ri-stampa con un rientro coerente in modo che un essere umano possa leggerlo Se passi un formattatore JSON rotto, il meglio che può fare è rifiutare Un validatore's tutto lo scopo è il caso rotto: ti dice dove e perché Il validatore Toolz.dev fa entrambi i lavori, perché una volta che ha confermato che un documento è valido lo ha già analizzato, quindi stampa abbastanza il risultato nello stesso passaggio Ma la caratteristica del titolo è la diagnosi, non il rientro.
Lo stesso rapporto vale con gli strumenti vicini. IL Minifier JSON spoglia gli spazi bianchi per ridurre un carico utile, il che ha senso solo su un input valido. IL Smistatore JSON riordina le chiavi per diff stabili, sempre su input valido Il JSON scappa e scappa tool si occupa di incorporare JSON all'interno di una stringa. e il Tester JSONPath query un documento che hai già confermato è ben formato La convalida è il passo che viene prima di tutti loro, motivo per cui è quello che eseguo per primo ogni volta che una risposta API o un file di configurazione si comporta in modo strano C'è un tour più ampio di come questi si incastrano nel Guida definitiva agli strumenti JSON.
Cosa ti dicono le statistiche della struttura?
Quando un documento viene convalidato, lo strumento riporta la sua forma: quanti oggetti e array contiene, quante chiavi, quante stringhe, numeri, booleani e nulli, quanto profondamente nidifica e le sue dimensioni sia in caratteri che in byte UTF-8. Questa non è decorazione Quando ti viene consegnata una risposta API sconosciuta, il numero di profondità ti dice a colpo d'occhio se hai a che fare con un record piatto o un albero profondamente annidato e il conteggio delle chiavi ti dice approssimativamente quanto lavoro analizzerà sarà.
La cifra dei byte conta più di quanto la gente si aspetti I limiti di dimensione della richiesta, i limiti di coda dei messaggi e i limiti delle colonne del database sono quasi sempre misurati in byte, non in caratteri, e i due differiscono nel momento in cui il tuo JSON contiene qualcosa al di fuori dell'ASCII Un'emoji o un nome accentato è un carattere sullo schermo ma due, tre o quattro byte sul filo Se un payload sta urtando contro un limite di 256 KB, il conteggio dei caratteri ti fuorvierà e il conteggio dei byte no. Il validatore calcola la vera lunghezza dei byte UTF-8 in modo che il numero che vedi sia il numero che il limite sta contando.
Come lo uso
Il mio flusso di lavoro è noioso e veloce, che è il punto Quando un'integrazione si rompe, copio il corpo di risposta grezzo direttamente dalla scheda di rete e lo incollo nel validatore Se è valido, il risultato verde e le statistiche mi dicono che il problema è da qualche altra parte, nel mio codice piuttosto che nei loro dati, e ho escluso un'intera classe di cause in due secondi Se non è valido, ottengo la riga e la colonna, lo risolvo e vado avanti Quando sto modificando manualmente un file di configurazione, lo incollo prima di impegnarmi, soprattutto per catturare la virgola finale che mi sembra sempre di lasciare dietro e la chiave duplicata occasionale da un copia-incolla Per chiunque assemblando il proprio kit, il validatore si siede accanto agli altri elementi essenziali nel Toolkit per sviluppatori web.
Anche l'angolo della privacy non è un ripensamento Le persone JSON che hanno più bisogno di convalidare è esattamente il JSON con cui dovrebbero stare più attenti: risposte API che trasportano token, file di configurazione con credenziali, payload con dati dei clienti Tutto ciò che il validatore fa accade nel tuo browser, in JavaScript, sulla tua macchina Nulla viene caricato, registrato o archiviato Puoi dimostrarlo aprendo la scheda di rete mentre convalidi, o disconnettendoti da internet e guardando lo strumento continuare a funzionare.
Domande frequenti
Perché il mio JSON dice che non è valido quando sembra a posto?
I motivi più comuni sono una virgola finale prima di una parentesi graffa o parentesi di chiusura, virgolette singole in cui JSON richiede virgolette doppie, una virgola mancante tra due membri o un commento, che JSON non consente affatto Tutti e quattro sono facili da perdere a occhio, specialmente in un file di grandi dimensioni Il validatore nomina quale ha trovato e ti dà la riga e la colonna esatte, quindi invece di scansionare l'intero documento salti direttamente al carattere su cui si è fermato.
Un singolo numero o stringa è valido JSON da solo?
Sì. Sotto RFC 8259, qualsiasi valore JSON è un testo JSON completo, quindi 42, "hello", true, e null tutti convalidare da soli La regola che il livello superiore doveva essere un oggetto o un array è venuto dal vecchio RFC 4627 ed è stato rimosso nel 2014 Uno strumento che rifiuta un valore nudo sta seguendo una specifica obsoleta.
Il validatore cambia o carica i miei dati?
No. Analizza il testo nel browser e non lo invia mai da nessuna parte Su un documento valido produce una copia abbastanza stampata per comodità, ma quella copia viene generata localmente e l'originale non viene mai trasmesso, registrato o archiviato Poiché non esiste un server di andata e ritorno, lo strumento funziona anche con la rete disconnessa una volta caricata la pagina.
Perché dovrei preoccuparmi delle chiavi duplicate se il JSON è ancora valido?
Perché un duplicato significa quasi sempre perdita di dati che non intendevi Lo standard consente chiavi duplicate ma lascia la loro gestione indefinita, e in pratica i parser mantengono solo l'ultimo valore e rilasciano il resto Quindi una configurazione dove timeout appare due volte in silenzio perde la prima impostazione Il validatore ti avverte di ogni tasto ripetuto con la sua posizione, che di solito è il momento in cui si individua una cattiva unione o un errore di copia-incolla.
Questo può convalidare JSON con commenti, come un file di impostazioni tsconfig o VS Code?
No, e questo è deliberato Quei file sono JSON con Commenti (JSONC) o JSON5, che sono formati separati che rilassano le regole Il validatore mira a rigoroso RFC 8259, quindi contrassegnerà un commento come un errore Se hai bisogno di commenti in un file di configurazione, che è un segnale il formato dovrebbe essere qualcosa costruito per esso, come YAML o TOML, piuttosto che JSON allungato oltre ciò che lo standard consente.
Qual è la differenza tra la convalida e la formattazione di JSON?
La convalida verifica se il testo obbedisce alla grammatica JSON e, in caso contrario, ti dice esattamente dove si rompe La formattazione presuppone che il testo sia già valido e regola solo i suoi spazi bianchi per la leggibilità Si raggiunge un validatore quando qualcosa non va e bisogna sapere cosa; si raggiunge un formattatore quando tutto va bene e si vuole solo che sia leggibile Questo strumento fa entrambe le cose, ma la sua ragione di esistere è la diagnosi.
Quanto grande può convalidare un file?
Comodamente nelle decine di megabyte, limitato solo dal tuo browser's memoria, perché l'intero documento è analizzato in un unico passaggio sul tuo dispositivo Non c'è un limite di dimensione di caricamento perché non c'è caricamento Per un file veramente enorme, nei gigabyte, un validatore della riga di comando di streaming è lo strumento migliore, poiché il browser tiene l'intero testo in memoria contemporaneamente.



