Italiano

Strumenti per sviluppatori · JSON formattatore e validatore

L'ordine delle chiavi è importante in JSON? Ordinamento, uguaglianza e RFC 8785

· Sfondo

json standard convalida

L'ordine delle chiavi è importante in JSON? Ordinamento, uguaglianza e RFC 8785 illustrati con token JSON e un preciso limite di convalida
Illustrazione vettoriale originale ToolAcre

La specifica JSON chiama gli oggetti non ordinati, ma i veri parser e serializzatori solitamente preservano l'ordine e gli schemi di firma dipendono da questo. Questo post chiarisce cosa dicono le specifiche, cosa fanno le implementazioni e come la canonicalizzazione risolve la tensione.

Stessi dati, byte diversi

`{"city":"Oslo","temp":4}` e `{"temp":4,"city":"Oslo"}` contengono gli stessi due nomi e valori, ma i loro byte di origine differiscono. Il rientro può aggiungere molte più differenze testuali senza modificare nessuno dei due valori analizzati. Ecco perché "equal JSON" necessita di una regola di confronto: stai confrontando testo, oggetti analizzati o una rappresentazione canonica definita da un altro protocollo?

ToolAcre può rimuovere il rumore degli spazi bianchi formattando entrambi i documenti con lo stesso rientro. Può anche ordinare ricorsivamente le chiavi degli oggetti quando tale opzione è selezionata. L'ordinamento modifica deliberatamente l'ordine dei membri ma non sposta mai gli elementi dell'array, poiché la posizione dell'array rappresenta i dati. Né la formattazione ordinaria né questo ordinamento facoltativo producono RFC 8785 canonico JSON, quindi l'output non deve essere sostituito con un formato di firma specificato.

Cosa dice RFC 8259: un oggetto è una raccolta non ordinata di coppie name/value e le implementazioni possono esporre l'ordine o meno

RFC 8259 descrive un oggetto come una raccolta non ordinata di coppie name/value. Pertanto, il software che tratta l'ordine dei membri come il significato di un oggetto JSON ordinario si basa su un comportamento esterno a quel modello astratto. Le matrici sono ordinate in modo esplicito, quindi `["draft","final"]` non è intercambiabile con `["final","draft"]`. L'ordine degli oggetti e l'ordine degli array non devono mai essere normalizzati dalla stessa regola.

RFC rileva inoltre che le librerie differiscono nel caso in cui espongono l'ordinamento dei membri ai chiamanti. Questo avvertimento è sufficiente per la progettazione portabile: non codificare la priorità o la sequenza posizionando un membro dell'oggetto prima di un altro. Se la sequenza è importante, rappresentala con un array o un campo esplicito. Un formattatore che mostra un ordine stabile è conveniente per gli esseri umani, ma non trasforma la posizione in una proprietà a livello di standard dell'oggetto.

Cosa fa effettivamente questo formattatore

Con l'ordinamento disabilitato, ToolAcre analizza il documento e serializza il valore JavaScript risultante. L'output segue il comportamento di enumerazione delle proprietà JavaScript anziché preservare il flusso di token originale byte per byte. La maggior parte delle chiavi di stringa ordinarie appaiono in un ordine familiare, mentre i nomi simili a indici interi possono essere emessi prima di altri nomi. Durante la riserializzazione è anche possibile normalizzare l'ortografia dei numeri e le scelte di escape.

Con l'ordinamento abilitato, il formattatore crea nuovi oggetti le cui chiavi sono alfabetizzate in ogni oggetto nidificato. Per `{"z":{"b":1,"a":2},"items":[{"d":4,"c":3},"x"]}`, i nomi degli oggetti diventano `items`, `z`; anche i nomi degli oggetti nidificati vengono ordinati; e l'array contiene ancora il suo oggetto prima di `"x"`. Ordinare gli oggetti all'interno di un array non significa ordinare l'array stesso.

Quando l'ordine dei byte è importante

L'ordine testuale è importante ogni volta che un processo consuma byte esatti anziché il valore astratto. Un hash di file, una chiave di cache, una firma digitale o un diff basato su riga cambiano quando i membri si spostano o cambiano gli spazi bianchi. Ciò non contraddice il modello a oggetti non ordinati; significa che il processo circostante ha scelto una rappresentazione in byte come parte del suo input. Le regole di rappresentanza devono poi essere esplicite e condivise.

Per le revisioni di routine, il rientro coerente e l'ordinamento alfabetico opzionale possono rendere le modifiche più facili da visualizzare. Per il lavoro crittografico o di protocollo, "sembra stabile" non è un contratto. Il produttore e il verificatore devono utilizzare l'esatto algoritmo di canonicalizzazione richiesto dal loro protocollo prima dell'hashing o della firma. Se non viene nominato alcun algoritmo, non dare per scontato che l'output di ToolAcre corrisponda a un altro serializzatore tra versioni, tempi di esecuzione o valori limite.

Perché l'ordinamento delle chiavi non è RFC 8785

RFC 8785 definisce lo schema di canonicalizzazione JSON per produrre byte ripetibili da dati compatibili. Il suo lavoro è più ampio del semplice posizionamento delle chiavi in ​​ordine alfabetico. Specifica l'ordinamento deterministico delle proprietà insieme all'esatto comportamento di serializzazione per stringhe e numeri e impone vincoli sul modello di input. Il rientro grazioso non fa parte dell'output canonico e l'ordinamento basato sulla locale non è un'approssimazione accettabile.

ToolAcre non presenta alcuna rivendicazione RFC 8785. La sua opzione di ordinamento è una funzionalità di leggibilità stratificata su `JSON.parse` e `JSON.stringify`; non convalida le precondizioni I-JSON né sostituisce le regole di serializzazione di RFC. Un valore come `1e-7`, una chiave contenente caratteri nonASCII o una stringa con escape può rivelare differenze tra un formattatore ordinato casual e un canonicalizzatore conforme. Utilizza un'implementazione JCS testata quando è richiesto JCS.

Esempio pratico: confrontare due documenti in modo equo

Confronta `{"meta":{"rev":2,"owner":"Mira"},"steps":["cut","pack"]}` con `{"steps":["cut","pack"],"meta":{"owner":"Mira","rev":2}}`. Formatta entrambi con due spazi e ordinamento disabilitato: gli spazi bianchi diventano coerenti, ma l'ordine dei membri root e nidificati può comunque differire. Analizza entrambi e confronta i campi previsti per stabilire l'equivalenza a livello di valore anziché dichiarare uguale il testo grezzo.

Attiva l'ordinamento ricorsivo delle chiavi ed entrambi gli esempi vengono visualizzati con lo stesso ordine degli oggetti mentre `steps` rimane `cut` quindi `pack`. Questo è utile per una differenza umana, ma è comunque la normalizzazione di ToolAcre, non la prova di RFC 8785. Se il secondo array fosse `["pack","cut"]`, le chiavi di ordinamento lascerebbero correttamente visibile la differenza perché la modifica dell'array modificherebbe la sequenza rappresentata.

Ciò che questo non copre

L'ordinamento delle chiavi non definisce una profonda uguaglianza per ogni applicazione. I nomi duplicati sono accettati da `JSON.parse`, che mantiene l'ultimo valore, quindi la formattazione può cancellare la prova che una fonte conteneva ripetizioni. I numeri interi di grandi dimensioni potrebbero già aver perso la precisione nel valore JavaScript. Un dominio può anche trattare gli array selezionati come insiemi, ma ToolAcre non può dedurre tale regola e pertanto non riordina mai gli array.

Il formattatore inoltre non confronta gli schemi, non applica i valori predefiniti, non normalizza Unicode o decide se due rappresentazioni numeriche sono accettabili per un sistema a valle. Quelli sono contratti separati. Utilizza la formattazione per ridurre il rumore della presentazione, un confronto strutturale appositamente creato per l'uguaglianza dei valori e il canonicalizzatore specificato per i byte esatti. Mescolare questi lavori sotto la parola “normalizzare” crea una falsa fiducia su ciò che è stato effettivamente confrontato.

Conclusione: l'ordine è insignificante per il modello e significativo per i byte

L'ordine dei membri dell'oggetto non ha significato nel modello di dati RFC 8259, a differenza dell'ordine degli array. I byte di origine registrano ancora sia l'ordine che gli spazi bianchi, quindi hash, firme e differenze di testo osservano distinzioni che un confronto orientato al valore potrebbe ignorare. Stabilisci quale livello è importante prima di scegliere uno strumento: identità testuale, equivalenza di valori analizzati e identità canonica definita dal protocollo sono tre domande diverse.

ToolAcre supporta i primi due flussi di lavoro solo indirettamente: la formattazione coerente chiarisce le differenze testuali e l'ordinamento ricorsivo alfabetico oggetto-chiave può rendere più silenziosi i confronti umani. Gli array non vengono mai ordinati. Il risultato non è RFC 8785 canonico JSON e non deve essere firmato come se lo fosse. Conserva l'input originale quando l'evidenza lessicale è importante, soprattutto perché l'analisi delle chiavi duplicate conserva solo l'ultimo valore.