Convertitore da XML a JSON
Converti XML in JSON o JSON in XML, con attributi @, #text, array decisi dall’intero documento e riga e colonna dove l’XML non è ben formato.
L’output apparirà qui
Cosa fa questo strumento
L’XML tende ad arrivare da sistemi che nessuno ha scelto: una risposta SOAP, un feed RSS, un file di configurazione, un’esportazione da qualcosa di più vecchio di JSON. Il codice che deve usarlo vuole JSON. Il caso inverso è altrettanto comune: un payload JSON destinato a un sistema che accetta solo XML. Questa pagina converte in entrambe le direzioni, nel tuo browser, e legge entrambi i formati con un unico insieme fisso di regole, così le due direzioni concordano su che cosa significa ogni chiave.
Ciò che la distingue è che la forma del JSON viene decisa dall’intero documento anziché dall’elemento che si sta leggendo, e la pagina lo dice. Ovunque quella decisione dia a un elemento una forma diversa da quella che avrebbe avuto da solo, un avviso sotto l’output nomina il percorso e la riga e la colonna in cui si è applicata per la prima volta. Ciò per cui JSON non ha posto, come i commenti o l’ordine del contenuto misto, viene segnalato allo stesso modo invece di sparire, e nell’altra direzione ogni riscrittura che XML impone al tuo JSON viene nominata nel punto in cui è avvenuta.
Le regole: @ per un attributo, #text per il testo
C’è un solo insieme di regole, e nessuna impostazione lo cambia. Un attributo diventa una chiave scritta come @ seguito dal nome dell’attributo, e il testo che deve condividere il suo elemento con qualsiasi altra cosa va sotto la chiave #text. Né @ né # possono iniziare un nome XML, quindi nessuna chiave scritta così può essere scambiata per un elemento figlio, ed è questo che permette di rileggere lo stesso JSON come XML senza indovinare. Applicate a un piccolo catalogo:
- L’elemento radice è l’unica chiave al livello superiore: un documento il cui elemento radice è catalog diventa un oggetto con l’unica chiave "catalog".
- Un elemento che non contiene altro che testo è quel testo: <title>Midnight Rain</title> diventa "title": "Midnight Rain".
- Un attributo è una chiave accanto agli elementi figli: <book id="bk101"> dà al libro "@id": "bk101", e ogni elemento figlio segue come chiave, nell’ordine in cui compare per la prima volta.
- Un elemento con attributi e testo tiene il testo sotto #text: <price currency="USD">44.95</price> diventa "price": {"@currency": "USD", "#text": 44.95}.
- Un elemento che si ripete sotto uno stesso genitore diventa un array: un libro il cui elemento author compare due volte ha "author": ["Gambardella, Matthew", "Knorr, Stefan"].
- I nomi vengono conservati esattamente come sono scritti, prefisso compreso: <dc:title> diventa la chiave "dc:title", una dichiarazione di spazio dei nomi diventa una chiave di attributo come "@xmlns:dc", e nulla viene risolto in un URI di spazio dei nomi.
Le entità e i riferimenti a carattere vengono decodificati, quindi & arriva come & e é come é, e una sezione CDATA è semplicemente testo. Gli spazi vuoti isolati tra gli elementi fanno parte della formattazione e vengono scartati; ogni altro tratto di testo viene conservato per intero e non viene mai tagliato. Le due normalizzazioni che ogni parser XML conforme applica vengono comunque prima: un ritorno a capo digitato nel testo arriva come avanzamento di riga, e una tabulazione o un’interruzione di riga digitate in un valore di attributo arrivano come spazio. Un riferimento a carattere è il modo in cui un documento conserva l’uno o l’altro.
Perché è l’intero documento a decidere la forma
Un convertitore che decide un elemento alla volta scrive gli autori del primo libro come array, perché sono due, e l’autore del secondo come stringa, perché è uno solo. Un elemento che porta un attributo è un oggetto in un record e testo semplice in quello successivo. Il codice scritto per il primo record si rompe sul secondo, e nulla lungo la strada ha detto che la forma poteva cambiare.
Per questo la forma viene decisa per percorso: i nomi degli elementi dalla radice fino a un elemento, scritti /catalog/book/author, senza posizioni, così che ogni autore di ogni libro stia su un solo percorso. Tutti gli elementi di un percorso vengono soppesati insieme:
- Array. Se l’elemento si ripete sotto uno stesso genitore, qualunque esso sia, ogni elemento del percorso viene scritto come array, compreso uno isolato.
- Oggetti. Se un qualsiasi elemento del percorso porta un attributo o un elemento figlio, ogni elemento del percorso viene scritto come oggetto, compreso uno che contiene solo testo, e tiene il suo testo sotto #text.
- Valori. Un percorso viene letto come numeri solo dove ogni suo valore si converte, e come booleani solo dove ogni valore è true o false, secondo la regola descritta più avanti a proposito di numeri e booleani.
- Elementi vuoti. Un elemento vuoto non prende parte a queste decisioni, e prende il genere che il suo percorso stabilisce.
Ovunque il risultato differisca da ciò che un elemento sarebbe stato da solo, la pagina lo dice una volta per il percorso, con la riga e la colonna del primo elemento che questo ha cambiato. In un catalogo in cui un libro ha più autori e un altro ne ha uno solo, quell’unico autore è comunque un array; dove un prezzo porta un attributo currency e un altro no, il prezzo semplice è comunque un oggetto, con il testo sotto #text. Entrambi i casi vengono segnalati, così nessuno dei due sorprende il codice che li legge.
Un campione con un solo record, e il campo «Sempre array»
La forma non può essere migliore del documento da cui viene decisa. Incolla un catalogo che contiene un solo libro e quel libro è un oggetto, il suo unico autore una stringa e il suo prezzo un numero, mentre lo stesso catalogo con un secondo libro accanto fa dei libri un array. Un percorso che in ciò che hai incollato compare ovunque una volta sola resta un valore singolo, e un percorso i cui valori si convertono tutti per caso resta un percorso di numeri finché non arriva un documento con un CAP che comincia con uno zero. Il JSON è affidabile esattamente quanto il campione è rappresentativo, quindi incolla più di un record ogni volta che puoi.
Per gli array c’è un rimedio che non dipende dal campione. Scrivi in «Sempre array» i nomi di elemento o i percorsi che devono essere array qualunque cosa mostri il documento, separati da virgole o spazi, e ogni percorso raggiunto da una voce viene scritto come array ovunque, anche dove compare una sola volta:
- Un nome da solo come item raggiunge ogni percorso che termina in un elemento chiamato item, ovunque si trovi.
- Un percorso come /rss/channel/item raggiunge quel solo percorso, scritto come sono scritti i percorsi sotto l’output, così se ne può copiare uno da lì.
- La corrispondenza è esatta: maiuscole e minuscole contano, e un prefisso fa parte del nome, quindi Item non raggiunge nessun item e link non raggiunge nessun atom:link.
- Ogni percorso che il campo ha trasformato in array viene segnalato come qualsiasi altra decisione. Una voce che non è né un nome né un percorso, e una che non ha raggiunto nessun elemento del documento, vengono elencate sotto il campo, e le voci che si applicano continuano ad applicarsi.
Il campo appartiene alla direzione «Da XML a JSON». Mantiene ciò che hai scritto quando cambi direzione e poi torni, e come ogni impostazione della pagina non viene conservato tra una visita e l’altra. I valori non hanno un campo del genere: un percorso che deve restare testo qualunque cosa contenga il campione è ciò a cui serve disattivare «Converti numeri e booleani», al prezzo che ogni altro valore diventi testo a sua volta.
Numeri, booleani, e perché 02134 resta testo
In XML tutto è testo, e trasformare in numeri JSON il testo che sembra numerico di solito è ciò che vuoi. È anche il modo in cui un CAP 02134 diventa 2134, e in cui un numero d’ordine lungo perde le ultime cifre. La regola qui è quella che usa il convertitore CSV di questo sito, e non ha bisogno di alcun elenco di casi speciali: il testo diventa un numero solo dove quel numero, riscritto, riproduce esattamente il testo. 42 lo fa, quindi viene convertito. 02134 no, e nemmeno 1.50, +5, 1e5 o un intero troppo lungo perché un double ne conservi ogni cifra. I booleani sono esattamente true e false, in minuscolo.
Ciò che questa pagina aggiunge è che la regola si applica a un intero percorso in una volta sola. Un percorso viene letto come numeri solo se ogni suo valore si converte, e come booleani solo se ogni valore è un booleano; un solo valore che perderebbe una cifra, oppure numeri e booleani che si incontrano su uno stesso percorso, lasciano come testo ogni valore di quel percorso. Ogni nome di attributo di un percorso viene deciso a sé. Un percorso lasciato come testo mentre alcuni dei suoi valori si sarebbero convertiti viene segnalato, nominando il percorso, e per un attributo il percorso termina sull’attributo, come in /catalog/book/@id.
«Converti numeri e booleani» è attivo quando la pagina si apre, come lo è l’interruttore corrispondente nella pagina CSV, e disattivarlo scrive ogni valore come testo. Il valore di una dichiarazione di spazio dei nomi non viene mai letto come numero, in nessuno dei due casi, perché lo standard Namespaces in XML definisce quel valore come un nome di spazio dei nomi, che è testo.
Elementi vuoti, e il null che un documento indica da sé
- Un elemento vuoto prende il genere che il suo percorso stabilisce. In un percorso di testo è la stringa vuota. In un percorso di numeri o booleani è null, e la pagina lo dice, dato che da solo l’elemento sarebbe stato testo vuoto.
- Vuoto significa niente del tutto: <zip> </zip> contiene uno spazio, e uno spazio è testo.
- Un percorso in cui ogni elemento è vuoto è testo, quindi ciascuno di essi è la stringa vuota. Lì nulla si legge come numero, e un null sarebbe un’informazione che il documento non ha mai dato.
- In un percorso scritto come oggetti, un elemento vuoto porta anch’esso #text, vuoto o null secondo la stessa regola, ovunque un altro elemento del percorso contenga testo: accanto a <price currency="USD">5</price>, un <price/> diventa {"#text": null}. Dove nessun elemento del percorso contiene testo, come nel caso di elementi immagine che portano solo un attributo src, nessuno di essi porta #text.
Un documento può anche indicare null da sé. Un elemento marcato xsi:nil="true", con quel prefisso legato allo spazio dei nomi XML Schema instance, è null in qualsiasi percorso, qualunque sia l’impostazione di «Converti numeri e booleani». La marcatura è il modo in cui il documento dice null e non dati, quindi nel JSON non compaiono né l’attributo né una dichiarazione di spazio dei nomi che non lega nient’altro. Funziona qualsiasi prefisso legato a quello spazio dei nomi, e i:nil="1" dice la stessa cosa; xsi:nil="false" è un dato ordinario, e un elemento marcato nil che ha comunque un contenuto viene lasciato com’è, perché leggerlo come null scarterebbe quel contenuto senza dire nulla.
Ciò per cui JSON non ha posto, segnalato invece che perso
Una parte di ciò che contiene un documento XML non ha posto in JSON. Ciò che ha un significato viene segnalato sotto l’output invece di essere scartato in silenzio:
- L’ordine del contenuto misto. In <p>Hello <b>world</b>, again</p> il testo viene raccolto sotto #text come "Hello , again" e l’elemento b sotto "b": ogni carattere e ogni elemento sopravvivono, ma non l’ordine in cui stavano. Gli elementi figli i cui nomi si alternano perdono il loro ordine allo stesso modo. Viene segnalato una volta per il percorso dell’elemento di cui è il contenuto, e solo dove l’ordine è andato davvero perso, quindi <p><b>Note:</b> the rest</p> non fa scattare nulla, perché l’ordine delle sue chiavi lo conserva.
- Commenti e istruzioni di elaborazione. Vengono omessi, con un avviso per ciascun genere che dice quante occorrenze c’erano e dove si trova la prima.
- Il DOCTYPE. Viene omesso anche questo, e il suo avviso dice che la DTD non è stata applicata: un valore predefinito che la DTD dichiara per un attributo manca dal JSON, perché questo strumento non legge la DTD.
- La dichiarazione XML in cima. Viene omessa senza avviso, perché descrive come è codificato il testo e non che cosa sono i dati.
Il JSON riconvertito in XML: l’XML più vicino, e ogni riscrittura nominata
Cambia direzione e le stesse regole funzionano al contrario: una chiave @ diventa un attributo, #text diventa il testo del suo elemento, un array diventa un elemento per ogni membro, e ogni altra chiave diventa un elemento figlio, con gli elementi figli nell’ordine in cui stanno le loro chiavi. Un null viene scritto come un elemento vuoto marcato xsi:nil="true", con lo spazio dei nomi XML Schema instance dichiarato una sola volta sull’elemento radice e solo quando viene scritto un null, così riconvertire dà di nuovo null invece di una stringa vuota. A parte il JSON che non si riesce ad analizzare, o che è annidato troppo in profondità per essere convertito, nulla viene rifiutato. Dove il tuo JSON ha una forma che XML non può portare così com’è, viene scritto l’XML ben formato più vicino e la riscrittura viene nominata sotto l’output, a un JSONPath che puoi incollare nel Tester JSONPath di questo sito:
- Tutto ciò che non è un unico elemento radice, che siano più chiavi al livello superiore, nessuna, un array al livello superiore o un valore isolato, viene scritto dentro <root>.
- Una chiave che non è un nome XML viene scritta con il nome più vicino con cui non è scritta nessun’altra chiave accanto: first name come first_name, e 1st come _1st.
- Un membro di un array che nessuna chiave nomina, che stia dentro un altro array o al livello superiore, viene scritto come elemento <item>.
- Una chiave @ o un #text che contiene un oggetto o un array viene scritto come elemento figlio, dato che né un attributo né un testo possono contenerne uno.
- Una chiave @ che contiene null viene omessa, e lo stesso vale per un #text che contiene null accanto a elementi figli, dato che XML dice null solo di un elemento intero.
- Un carattere che XML 1.0 non può contenere affatto, nemmeno come riferimento, viene sostituito, e la pagina dice dove.
L’escape fa parte della scrittura di XML ben formato, non è un’opzione. Un < e una & vengono sempre sottoposti a escape. In un valore di attributo si fa lo stesso con una virgoletta doppia, perché il valore è scritto tra due di esse; una tabulazione, un avanzamento di riga o un ritorno a capo lì viene scritto come riferimento a carattere, perché altrimenti un parser lo trasformerebbe in uno spazio. Nel testo, un ritorno a capo viene scritto come riferimento, perché altrimenti un parser lo trasformerebbe in un avanzamento di riga, e ]]> non viene mai scritto così com’è. È questo che permette di rileggere il valore come il valore che hai scritto.
Che cosa dà la riconversione, detto prima che tu converta
Alcuni XML sono ben formati e tuttavia si rileggono come qualcosa di diverso dal JSON da cui sono stati scritti, quindi la pagina legge l’XML che ha appena scritto, con le stesse regole che usa l’altra direzione, e dice dove la risposta differisce. Un array di un solo membro si rilegge come il suo unico membro, a meno che gli stessi elementi non si ripetano sotto uno stesso genitore altrove nel documento. Un array vuoto non scrive alcun elemento e un #text vuoto non scrive alcun testo, quindi ciascuno si rilegge come nulla. Un oggetto che non contiene nulla che si scriva come attributo o elemento figlio si rilegge come valore semplice, e dove gli stessi elementi altrove fanno decidere al documento un array o un oggetto che il tuo JSON non aveva, viene detto anche questo. Ciascuno di questi casi viene scritto come lo ha il tuo JSON, e segnalato.
«Usa come input» sposta l’output nel riquadro di input e cambia la direzione, così ciò che torna, e ciò che viene segnalato, è a un clic di distanza. Dove non viene segnalato nulla, ciò che torna è il tuo JSON, a parte ciò che XML non conserva. Il testo XML non registra se un valore era un numero, un booleano o una stringa: con «Converti numeri e booleani» attivo, una stringa che riproduce esattamente un numero può tornare come quel numero, e se è disattivato ogni valore torna come testo. E un attributo, o un #text vuoto o null, può tornare in un altro posto tra le chiavi che ha accanto, perché XML non conserva quella posizione.
Il giro completo che parte dall’XML promette meno, di proposito. Il testo che hai incollato non torna: la dichiarazione, la formattazione, i commenti e tutto il resto segnalato all’andata sono spariti. Ciò che resta stabile è l’XML che la pagina scrive: convertilo in JSON e poi riconvertilo, con le stesse impostazioni, e torna lo stesso XML.
Quando l’XML o il JSON non si può leggere
Un documento che il parser XML non riesce a leggere viene rifiutato con una frase che dice che cosa non va, e una riga e una colonna ovunque ci sia un punto da indicare: un elemento che non viene mai chiuso, un valore di attributo senza virgolette e una & che non inizia alcun riferimento hanno ciascuno una frase propria. Un tag di chiusura che non corrisponde all’elemento ancora aperto lo dice, poi mostra il tag di chiusura di cui quell’elemento ha bisogno, che nomina l’elemento rimasto aperto. Il JSON che non si riesce ad analizzare viene rifiutato allo stesso modo, con la riga e la colonna in cui il suo parser si è fermato, ovunque questo si possa misurare.
Sotto una frase che indica un punto, la pagina mostra la tua stessa riga con il carattere errato segnato, il che conta soprattutto per l’XML o il JSON minimizzato, dove l’intero documento è una sola riga. Una riga lunga viene ridotta al tratto intorno al segno, con i puntini di sospensione dove è stata tagliata. Un carattere errato che non disegna nulla, come la fine del testo, una tabulazione o un contrassegno di ordine dei byte, viene segnato su un simbolo visibile che ne fa le veci. La colonna conta come JavaScript conta una stringa, in unità di codice UTF-16, quindi ogni emoji o ideogramma raro prima del segno la sposta avanti di due invece che di uno.
Un documento annidato più in profondità di quanto il sito consenta viene rifiutato anch’esso, in entrambe le direzioni, e la sua frase indica il limite.
Domande frequenti
- Perché un singolo elemento viene scritto come array?
- Perché un elemento dello stesso percorso si ripete sotto uno stesso genitore altrove nel documento, e il percorso viene deciso una volta per il documento intero. Il codice che legge il valore come array funziona allora per ogni record, compresi quelli con un solo elemento. La pagina nomina il percorso, con la riga e la colonna del primo elemento che questo ha cambiato. Per avere un array dove il tuo campione ne contiene uno solo, indica l’elemento in «Sempre array».
- Perché nel mio JSON c’è un numero tra virgolette?
- Perché qualche valore dello stesso percorso non sopravvivrebbe come numero, che sia per uno zero iniziale, per uno zero finale dopo il punto decimale, per un segno più o per un esponente, oppure perché su quel percorso si incontrano numeri e booleani. Un percorso così è testo ovunque, e la pagina lo nomina. I suoi valori si convertono non appena ciascuno di essi è scritto come il numero si riscrive, 2134 invece di 02134.
- Che fine fanno commenti, istruzioni di elaborazione e DOCTYPE?
- Vengono omessi dal JSON, e ogni genere viene segnalato con quante occorrenze c’erano e dove si trova la prima. L’avviso sul DOCTYPE dice inoltre che la DTD non è stata applicata, quindi manca qualsiasi valore predefinito di attributo che dichiari.
- Controlla il mio XML rispetto a una DTD o a un XSD?
- No. Legge XML ben formato e dice dove non è riuscito a leggere un documento, ma non convalida rispetto a una DTD o a un XSD, e non applica nulla di ciò che una DTD dichiara. Per questo un DOCTYPE viene segnalato come non applicato invece di essere ignorato in silenzio.
- Come viene scritto null in XML, e torna indietro?
- Come un elemento vuoto marcato xsi:nil="true", con lo spazio dei nomi XML Schema instance dichiarato una sola volta sull’elemento radice. Riconvertire quell’XML dà di nuovo null, mentre un semplice elemento vuoto sarebbe tornato come stringa vuota in qualsiasi percorso letto come testo. Se il tuo JSON usa già il prefisso xsi per un nome suo, la pagina dichiara invece un prefisso libero.
- Che fine fa una chiave con uno spazio?
- Viene scritta con il nome più vicino che XML ammette, quindi first name diventa first_name, e la pagina nomina la chiave con il suo JSONPath insieme al nome che ha preso. Incolla quel JSONPath nel Tester JSONPath di questo sito per selezionare ogni valore a cui si è applicata la riscrittura.
- Perché riconvertire non mi restituisce il mio XML originale?
- Perché JSON non ha posto per una parte di ciò che contiene un file XML: la dichiarazione, la formattazione tra gli elementi, i commenti, le istruzioni di elaborazione, il DOCTYPE e l’ordine del contenuto misto. Ciò che aveva un significato è stato segnalato all’andata. Ciò che resta stabile è l’XML che la pagina scrive: portalo in JSON e poi riconvertilo, con le stesse impostazioni, e torna lo stesso XML.
- Qualcosa di ciò che incollo viene inviato a un server?
- No. Entrambe le direzioni girano interamente nel tuo browser, quindi il documento che incolli, che sia una risposta di un’API, un feed o un file di configurazione che contiene delle credenziali, non lascia mai il tuo dispositivo.
Strumenti correlati
- Formattatore JSON
Convalida e abbellisce il JSON, con posizioni di errore chiare.
- Formattatore SQL
Formatta e abbellisce SQL — più dialetti.
- Formattatore XML
Formatta XML e controlla che sia ben formato — abbellisci o minimizza.
- Convertitore da CSV a JSON
Converti CSV in JSON e viceversa — virgolette gestite come si deve.