Vai al contenuto
OneKitly

Da CSV a JSON: i cinque casi che rompono qualsiasi convertitore

Pubblicato il 17/07/2026 · 15 min di lettura · Strumenti per sviluppatori

Daniel Okonkwo

Daniel OkonkwoSviluppatore front-end e redattore Tech presso OneKitly

Performance web · Formati di file

Verificato su 4 fonti

Vedi il profilo
In breve

Il CSV non ha una norma, solo la RFC 4180: una RFC informativa che descrive ciò che la maggior parte dei programmi faceva già nel 2005, non una regola vincolante. Cinque casi separano un parser che funziona da uno che corrompe in silenzio. Uno: un delimitatore dentro un campo tra virgolette. name,city / Tom,"Paris, France" resta su due colonne, e una virgoletta raddoppiata all'interno esce come una sola. Due: un a capo dentro un campo tra virgolette. Il parser legge fino alla virgoletta di chiusura e non fino a fine riga, quindi un indirizzo su due righe sopravvive come un solo valore. Tre: i tipi. La conversione è disattivata di default; attivala e 1 diventa il numero 1, mentre 0044, 1.0, 1e3, 2026-08-18 e 9007199254740993 restano stringhe, perché una cella si converte solo se il numero si ristampa esattamente come è arrivato. true diventa un booleano ma TRUE no, perché i booleani JSON sono minuscoli, e null diventa il null di JSON — cosa che sorprende il giorno in cui un cognome è Null. Quattro: intestazioni duplicate. name,name,name dà name, name_2 e name_3 invece di una sola colonna superstite, e un'intestazione vuota diventa column2. Cinque: la codifica. Il BOM UTF-8 viene tolto, e il browser assorbe i BOM di UTF-8 e UTF-16 prima che lo strumento veda il testo, ma non c'è un selettore di codifica, quindi un export Windows-1252 arriva come Andr�, e U+FFFD non si disfa. Due casi che non salva: un campo tra virgolette preceduto da uno spazio, Tom, "Paris, France", non è trattato come citato, e una riga di suggerimento Excel sep=; viene consumata come intestazione.

Delimitatori tra virgolette, a capo incorporati, tipi ambigui, intestazioni duplicate e codifica. Ogni caso è passato dal convertitore e qui c'è l'output esatto — compresi i due che non salva.

La RFC 4180 è una descrizione, non una regola

Tutti citano la RFC 4180 come se fosse lo standard del CSV. La sua stessa intestazione dice il contrario: è informativa, il che in gergo IETF significa che non specifica alcuno standard Internet. È stata pubblicata nel 2005 per mettere per iscritto ciò che i programmi già facevano, e lo dice del proprio oggetto: la regola 5 osserva che alcuni programmi, Microsoft Excel compreso, non usano affatto le virgolette. È questa la radice di ogni problema in questo articolo. Non c'è un'autorità a cui appellarsi quando due strumenti divergono sullo stesso file, perché nessuno dei due sta violando alcunché.

La RFC definisce in effetti due cose che aiuterebbero, e nessuna sopravvive al passaggio in un file. Definisce un parametro header sul tipo di media text/csv, con i valori present e absent, per dire al destinatario se la prima riga contiene nomi di colonna. E dice che l'uso comune è US-ASCII, con altri set di caratteri portati dal parametro charset. Sono entrambi parametri MIME: vivono su una risposta HTTP o su un allegato, non dentro i byte. Salva gli stessi dati come vendite.csv ed entrambe le informazioni sono sparite. È per questo che ogni lettore CSV al mondo ha una casella «la prima riga è un'intestazione», ed è per questo che la codifica va indovinata.

Casi 1 e 2 — il delimitatore e l'a capo dentro un campo tra virgolette

Questi due sono lo stesso bug con abiti diversi, e nascono entrambi dallo spezzare sul carattere grezzo invece che analizzare. Un convertitore che fa text.split(",") trasforma Tom,"Paris, France" in tre colonne, e ogni riga sotto eredita la colonna in più. Un convertitore che fa prima text.split("\n") taglia in due un indirizzo su due righe e produce una riga con un solo campo. Il rimedio è lo stesso: percorrere la stringa carattere per carattere, tenere un flag «sono dentro le virgolette», e trattare un delimitatore o un a capo come strutturali solo quando il flag è abbassato.

Passano entrambi. name,address / Tom,"12 rue A\nParis" / Ann,"3 rue B" restituisce esattamente due oggetti, il primo con un indirizzo su due righe. Una virgoletta raddoppiata viene de-escapata in ingresso, quindi "He said ""hi"" loudly" torna come He said "hi" loudly. Vale la pena conoscere uno scarto rispetto alla RFC: lo strumento normalizza ogni CR LF in LF prima di analizzare, perciò un a capo che era CR LF dentro un campo citato esce dal convertitore come LF nudo. Non si perde nulla, ma se confronti l'andata e ritorno byte per byte, la differenza è lì.

Il caso che non salva è quello su cui la RFC è esplicita. La sezione 2.4 dice che gli spazi fanno parte del campo e non vanno ignorati: in Tom, "Paris, France" il primo carattere del campo è uno spazio e la virgoletta che segue è solo un carattere, non un delimitatore di apertura. Il parser dà ragione alla RFC e produce due colonne rotte, " Paris e France". Chi scrive quella riga voleva quasi sempre un campo citato. Se il tuo esportatore mette uno spazio dopo il delimitatore, toglilo prima di convertire, altrimenti le virgolette sono decorative.

Caso 3 — i tipi, e il test di andata e ritorno che salva i numeri di telefono

Il CSV non ha tipi. Ogni cella è testo, e nel momento in cui produci JSON devi decidere se 1 è la stringa "1" o il numero 1. Per impostazione predefinita il convertitore non decide nulla: la conversione è un interruttore e parte spento, quindi un'esecuzione semplice dà un array di oggetti i cui valori sono tutti stringhe. È il default giusto, perché una stringa è sempre recuperabile e un numero no.

Attiva l'interruttore e la regola è un solo test di andata e ritorno: una cella diventa numero solo se ristampare quel numero restituisce esattamente i caratteri arrivati. Eseguendolo, 1 diventa 1, ma 0044 resta "0044" perché Number("0044") stampa 44. 1.0 resta "1.0" perché stampa 1. 1e3 resta "1e3" perché stampa 1000. .5 e +1 restano stringhe per lo stesso motivo. E 9007199254740993 resta una stringa, perché il double più vicino in JavaScript stampa 9007199254740992: un convertitore senza questa protezione cambia in silenzio l'ultima cifra di un identificatore lungo, e nulla a valle te lo dirà mai.

Tre cose sfuggono al test di andata e ritorno, perché passano da un confronto letterale. true e false diventano booleani, ma solo in minuscolo: TRUE, True e FALSE restano stringhe, cosa che conta perché Excel scrive i booleani in maiuscolo e le interfacce francese e tedesca scrivono VRAI e WAHR. null diventa il null di JSON, e lì c'è una trappola vera: un campo di testo il cui valore sono le quattro lettere null non è la stessa cosa di un valore assente, e dopo la conversione non li distingui più. E con le date non si fa nulla: 2026-08-18 resta la stringa "2026-08-18", che è la risposta giusta, perché un convertitore che analizza le date deve scegliere un fuso orario e sbaglierà.

Caso 4 — intestazioni duplicate, intestazioni vuote, righe irregolari

Un CSV può ripetere il nome di una colonna; un oggetto JSON no. Con name,name,name sopra a,b,c, l'implementazione ingenua scrive tre volte la stessa chiave e JSON tiene l'ultima: ottieni {"name": "c"} e due colonne di dati sono sparite senza alcun errore. Questo convertitore rinomina: name, name_2, name_3. Gestisce anche il caso successivo, quando il nome inventato collide con uno vero — name,name,name_2 dà name, name_2 e name_2_2, perché il rinominatore controlla su tutto ciò che è già stato usato e non solo sulle intestazioni originali.

Una cella di intestazione vuota riceve un nome posizionale: name,,name, sopra a,b,c,d dà name, column2, name_2 e column4. I nomi di intestazione vengono ripuliti, quindi " name , age " produce name e age. E la larghezza dell'output è quella della riga più larga del file, non quella dell'intestazione: a,b,c sopra le due righe 1,2 e 3,4,5,6 dà quattro chiavi a ogni oggetto, con c vuoto sulla riga corta e un column4 che porta il 6 di cui l'intestazione non aveva tenuto conto. Non si scarta nulla, ed è la scelta giusta per un convertitore: troncare in silenzio una riga lunga significa distruggere proprio la riga che andava guardata.

Caso 5 — la codifica, quella che lo strumento non può riparare

Un file CSV sono byte. Nulla al suo interno dice quale tabella trasforma quei byte in caratteri, e la RFC 4180 mette quell'informazione in un parametro MIME che un file su disco non porta. Due meccanismi coprono in parte il vuoto. Un byte order mark all'inizio del file identifica UTF-8, UTF-16 LE e UTF-16 BE, e il lettore di file del browser lo consuma: trascina un file UTF-16 LE con BOM nello strumento e il testo arriva decodificato correttamente, con il marchio già tolto. Lo strumento toglie poi di nuovo un BOM per conto suo, il che copre il caso in cui il marchio arriva dagli appunti e non da un file.

Il vuoto che resta aperto è il file senza alcun marchio, che è la maggioranza. Salva un foglio di calcolo come CSV semplice su una macchina Windows dell'Europa occidentale e ottieni Windows-1252, un byte per carattere, senza BOM. Questo convertitore non ha un selettore di codifica: il lettore ripiega su UTF-8, il byte E9 che significava é non è UTF-8 valido, e viene sostituito da U+FFFD. Lo strumento poi analizza senza intoppi e restituisce {"name": "Andr�", "city": "K�ln"} senza alcun avviso, perché dal suo punto di vista non è andato storto nulla. U+FFFD non conserva traccia del byte sostituito, quindi non è riparabile a posteriori: riesporta il file in UTF-8, oppure incolla il testo invece di trascinare il file, perché il testo negli appunti è già stato decodificato dall'applicazione che lo possiede.

Un ultimo caso di codifica ha il filo tagliente: UTF-16 senza byte order mark. Non c'è nulla da fiutare, quindi il file viene letto come UTF-8, un byte su due è uno zero, e quello che torna è un unico oggetto la cui chiave contiene caratteri NUL. Sembra spazzatura e non testo leggermente sbagliato, e questo è l'esito buono: te ne accorgi subito. I fallimenti pericolosi sono quelli silenziosi, e Windows-1252 letto come UTF-8 è il più silenzioso di tutti, perché le colonne combaciano alla perfezione e solo le lettere accentate sono sbagliate.

Il sesto caso che nessuno elenca: la riga sep=

Excel accetta una prima riga nella forma sep=; come istruzione su quale carattere separa i campi, e molte routine di esportazione la emettono perché un file a punto e virgola si apra bene in un lettore il cui separatore di elenco è la virgola. Non è nella RFC 4180 e non lo è mai stata: è una convenzione di fornitore diffusasi perché funziona. Per un convertitore che non ne ha mai sentito parlare, è semplicemente il primo record del file.

È esattamente ciò che succede qui. Dai al convertitore sep=; seguito da Name;Ville;Montant e due righe di dati: il rilevamento automatico sceglie correttamente il punto e virgola — perché la riga sep= ne contiene uno — ma il passo dell'intestazione se la mangia. Ottieni tre oggetti invece di due, con le chiavi "sep=", column2 e column3, e i veri nomi di colonna Name, Ville e Montant compaiono come valori del primo. È evidente appena guardi l'output, e invisibile se lo inoltri direttamente altrove. Cancella la prima riga prima di convertire, oppure converti prima il delimitatore e lascia che il convertitore di delimitatore riscriva il suggerimento per te.

Cinque input passati nel convertitore da CSV a JSON, con l'output realmente prodotto
InputCosa escePerché
Tom,"Paris, France"Due campi: Tom e Paris, FranceIl parser tiene uno stato «tra virgolette»; un delimitatore citato è dato
Tom, "Paris, France" (spazio dopo la virgola)Tre campi: Tom, " Paris e France"RFC 4180 sezione 2.4: lo spazio fa parte del campo, quindi la virgoletta non apre nulla
0044 con la conversione dei tipi attivaLa stringa "0044"Number("0044") stampa 44, che non è ciò che è arrivato, quindi la cella resta com'è
TRUE con la conversione dei tipi attivaLa stringa "TRUE"; solo true minuscolo diventa booleanoIl test è un confronto letterale con le due parole chiave JSON, che sono minuscole
name,name,name sopra a,b,cChiavi name, name_2 e name_3 — tutti e tre i valori conservatiUna chiave ripetuta in un oggetto distrugge dati: la seconda e la terza vengono rinominate
Un file Windows-1252 trascinato nello strumentoAndr� e K�ln, analizzati senza intoppi e senza avvisoNessun selettore di codifica: il lettore assume UTF-8 e sostituisce ogni byte non valido
Un file che inizia con sep=;Il punto e virgola è rilevato bene, ma sep= diventa la prima chiave e l'intestazione vera diventa una riga di datiIl suggerimento è una convenzione Excel, estranea a qualsiasi definizione di CSV: il parser lo legge come record
Convertitore da CSV a JSONAnalizza testo CSV (con riga di intestazione) in un array JSON di oggetti, gestendo i campi tra virgolette. Trascina un file invece di incollarlo: viene letto nel browser e non viene mai inviato.Prova lo strumento

Domande frequenti

Conviene attivare la conversione dei tipi o lasciarla spenta?
Lasciala spenta, a meno che qualcosa a valle non richieda numeri veri. Una stringa è una rappresentazione senza perdita di ciò che c'era nella cella; un numero è una rappresentazione con perdita, e la perdita è irreversibile. La protezione di andata e ritorno fa sì che proprio questo strumento non rovini 0044, 1.0 né un identificatore a 19 cifre, ma convertirà una colonna di codici postali privi di zero iniziale: 75001 e 75008 diventano numeri mentre un codice olandese come 1012 AB resta stringa — una colonna, due tipi, e chi consuma il JSON deve gestirli entrambi. Se ti servono numeri, converti dopo le colonne che ti interessano, dove puoi nominarle, invece di lasciare che un'euristica decida colonna per colonna.
Come fa il convertitore a sapere che il mio file usa i punti e virgola?
Conta i delimitatori candidati — virgola, punto e virgola, tab e barra verticale — solo sul primo record, saltando ciò che sta tra virgolette, e prende il più frequente. Leggere solo il primo record è voluto: un'intestazione come "Nom;Prénom" non deve essere valutata da una virgola sepolta in un indirizzo citato trecento righe più giù. Il limite ne è lo specchio. Se la tua intestazione contiene una virgola e le righe di dati usano i punti e virgola, il rilevatore sceglie la virgola e ogni riga diventa un unico campo. Due sintomi lo tradiscono all'istante: una sola chiave per oggetto, e una chiave il cui nome è l'intera riga di intestazione. Nel dubbio, imposta il delimitatore esplicitamente invece di affidarti al rilevamento.
Perché i miei caratteri accentati sono diventati punti interrogativi o rombi neri?
Perché il file non era UTF-8 e nulla lo ha detto al lettore. Il rombo nero con punto interrogativo è U+FFFD, il carattere di sostituzione Unicode, ed è ciò che un decodificatore emette quando una sequenza di byte non è valida nella codifica che gli è stata imposta. Il tuo file era quasi certamente Windows-1252 o ISO 8859-1, dove é è il singolo byte E9; UTF-8 ha bisogno di due byte per é, ed E9 da solo non è l'inizio legale di nulla. Il danno avviene prima che giri il parser CSV, quindi nessuna impostazione CSV lo annullerà. Apri l'originale in un editor che ti faccia scegliere la codifica, salvalo come UTF-8 e riconverti. Se il file viene da un foglio di calcolo, esportalo con l'opzione UTF-8 invece che come CSV semplice.
Le mie righe non hanno tutte lo stesso numero di campi. Perderò dei dati?
No. La larghezza dell'output è quella della riga più larga del file, comprese le righe più larghe dell'intestazione. Una riga corta riceve stringhe vuote per le colonne mancanti; una riga lunga riceve chiavi extra chiamate column4, column5 e così via per i campi che l'intestazione non ha mai nominato. Nulla viene troncato, e questo conta: una riga troppo lunga è di solito il sintomo di un delimitatore non protetto più in alto, e troncare cancellerebbe la prova. Se vedi column4 nel tuo JSON e l'intestazione aveva solo tre nomi, cerca un campo con un delimitatore non citato — è lì che il file è andato storto.
Esiste una versione di CSV senza questi problemi?
Dentro del CSV stesso no, perché il formato non ha dove mettere i metadati che risolverebbero le questioni. Ciò che esiste sono convenzioni sovrapposte: un file di schema che accompagna e nomina le colonne e i loro tipi, un profilo di esportazione fisso concordato fra i due sistemi, o un formato che porta con sé i propri tipi. Se controlli entrambe le estremità, JSON Lines — un oggetto JSON per riga — risolve in un colpo virgolette, a capo e tipi, al prezzo di un file più grande che non si apre in un foglio di calcolo. Se non controlli entrambe le estremità, la risposta pratica è essere noiosi: UTF-8 con BOM, virgola o punto e virgola in modo costante, tutti i campi citati, nessuna riga sep=, e un'intestazione con nomi unici e privi del delimitatore.

Articoli che potrebbero interessarti

Tutte le guide
SpiegazionePunto e virgola, tab, barra verticale: scegliere un delimitatore che sopravviva al viaggioPerché la lingua di chi legge decide il delimitatore, che cosa fa il convertitore alle virgolette quando cambi, che cos'è davvero la prima riga sep=, e il conteggio delle celle citate sullo stesso export scritto in cinque modi.SpiegazioneDa JSON a CSV quando la struttura è annidata: perché non esiste una risposta giustaI due stessi ordini escono con cinque colonne da un convertitore e dieci da un altro, e nessuno dei due sbaglia. Percorsi con punti, array di scalari, array di oggetti e record con chiavi diverse: quattro decisioni, prese per te e quasi sempre in silenzio.GuidaIncollare una tabella in una pull request: che cosa si rompe, e i due caratteri che la romponoUna tabella Markdown vieta esattamente due caratteri dentro una cella: la barra verticale e l'a capo. Ecco che cosa fa ciascuno, come li tratta un convertitore, perché l'escape va applicato nell'ordine giusto, e perché il riempimento non conta mai.TutorialCome convertire JSON in CSV: appiattire array di oggetti in righe e colonneUna guida pratica per trasformare un array JSON di oggetti in un file CSV pulito, incluso l'appiattimento dei campi annidati e i casi limite.GuidaTrasporre una tabella le cui righe avrebbero dovuto essere colonneChe ne è della riga di intestazione, delle righe di lunghezza diversa, dei tipi — e l'unica cosa con cui trasporre viene regolarmente confuso e che non può fare.SpiegazionePerché il tuo CSV rovina accenti e date in ExcelDietro la stessa frase si nascondono tre guasti completamente diversi. Uno è la codifica, uno il separatore, uno Excel che indovina i tipi mentre apre il file — e il rimedio è diverso per ciascuno. Ecco come distinguerli in cinque secondi.

Strumenti correlati

Questo descrive ciò che questi convertitori fanno oggi, verificato eseguendoli, e non ciò che una norma imponga a un convertitore. Il CSV non ha una norma prescrittiva: la RFC 4180 è informativa e descrive una prassi diffusa, perciò due strumenti apparentemente corretti possono divergere sullo stesso file senza che nessuno sbagli. L'appiattimento, il riconoscimento dei tipi e quello degli array sono convenzioni, non regole. Prima di convertire dati che non potrai riesportare, passa prima su una copia e confronta il numero di righe e colonne alle due estremità.

Fonti

Hai notato un errore in questo articolo?