CSV to JSON JavaScript — Converter + Code Examples
Usa il Da CSV a JSON gratuito direttamente nel tuo browser — nessuna installazione.
Prova Da CSV a JSON online →La maggior parte dei dati CSV che incontro arriva come stringa flat da un upload di file, un export da database, o un'API che parla ancora il formato degli anni '70. Per convertire CSV in JSON in JavaScript, ti servono due cose che il linguaggio ti fornisce gratuitamente: lo splitting delle stringhe per analizzare le righe e JSON.stringify() per serializzare il risultato. Nessun pacchetto npm necessario per le basi — questa guida copre l'intera pipeline da un'utility csvToJson() riutilizzabile fino a PapaParse e file I/O con Node.js. Per conversioni rapide senza codice, il convertitore CSV in JSON online lo gestisce istantaneamente. Tutti gli esempi sono pensati per Node.js 18+ e i browser moderni.
- ✓Dividi il CSV per newline, estrai le intestazioni dalla riga 0, mappa le righe rimanenti su oggetti, poi JSON.stringify(array, null, 2) per un output formattato.
- ✓JSON.stringify() produce una stringa; JSON.parse() la riconverte in un array JavaScript attivo — sapere quale dei due hai prima di operare su di esso.
- ✓Le istanze di Map non si serializzano automaticamente in JSON — chiama prima Object.fromEntries(map).
- ✓Per CSV con campi tra virgolette, virgole nei valori o newline nelle celle, usa PapaParse o csv-parse invece dello splitting manuale.
- ✓csvtojson (npm) gestisce la coercizione dei tipi, lo streaming e i casi limite di RFC 4180 in una singola chiamata.
Cos'è la Conversione da CSV a JSON?
La conversione da CSV a JSON trasforma un formato testuale flat delimitato da virgole in un array strutturato di oggetti dove ogni riga diventa un oggetto JavaScript con chiavi corrispondenti alle intestazioni di colonna. Il formato CSV non ha tipi di dati — tutto è una stringa. JSON aggiunge struttura, annidamento e tipi espliciti (numeri, booleani, null). Questa conversione è il primo passo in quasi ogni pipeline di dati che inizia con un export da foglio di calcolo, un dump di un sistema legacy, o un file caricato dall'utente. I dati sottostanti restano gli stessi; il formato cambia da colonne basate sulla posizione a proprietà con nome.
nome,email,ruolo,attivo Marco Rossi,mrossi@nexuslabs.io,Responsabile Ingegneria,true Giulia Ferrari,gferrari@nexuslabs.io,Product Manager,true
[
{
"nome": "Marco Rossi",
"email": "mrossi@nexuslabs.io",
"ruolo": "Responsabile Ingegneria",
"attivo": "true"
},
{
"nome": "Giulia Ferrari",
"email": "gferrari@nexuslabs.io",
"ruolo": "Product Manager",
"attivo": "true"
}
]csvToJson() — Costruire una Funzione di Conversione Riutilizzabile
L'intera pipeline CSV-to-JSON in JavaScript si articola in tre passaggi: dividi la stringa CSV per newline per ottenere le righe, estrai le intestazioni dalla prima riga con split(','), poi mappa ogni riga rimanente su un oggetto JavaScript semplice dove le chiavi provengono dalle intestazioni e i valori dalle posizioni di colonna corrispondenti. La chiamata finale a JSON.stringify() converte quell'array di oggetti in una stringa JSON. Ecco una versione minimale funzionante:
function csvToJson(csv) {
const lines = csv.trim().split('\n')
const headers = lines[0].split(',').map(h => h.trim())
const rows = lines.slice(1)
.filter(line => line.trim() !== '')
.map(line => {
const values = line.split(',')
return Object.fromEntries(
headers.map((header, i) => [header, values[i]?.trim()])
)
})
return JSON.stringify(rows, null, 2)
}
const csv = `server,port,region,status
api-gateway,8080,us-east-1,healthy
auth-service,8443,eu-west-1,degraded
payments-api,9090,ap-south-1,healthy`
console.log(csvToJson(csv))
// [
// { "server": "api-gateway", "port": "8080", "region": "us-east-1", "status": "healthy" },
// { "server": "auth-service", "port": "8443", "region": "eu-west-1", "status": "degraded" },
// { "server": "payments-api", "port": "9090", "region": "ap-south-1", "status": "healthy" }
// ]Questa funzione gestisce le basi: newline finali, righe vuote, spazi attorno ai valori. Ogni campo CSV passa come stringa. Nota che port è "8080" (una stringa), non 8080 (un numero). Se hai bisogno di tipi corretti nell'output JSON, devi forzarli tu stesso. Ecco una versione estesa con rilevamento dei tipi:
function coerceValue(val) {
if (val === undefined || val === '') return null
if (val === 'true') return true
if (val === 'false') return false
if (val === 'null') return null
const num = Number(val)
if (!isNaN(num) && val.trim() !== '') return num
return val
}
function csvToJson(csv, { coerce = false } = {}) {
const lines = csv.trim().split('\n')
const headers = lines[0].split(',').map(h => h.trim())
const rows = lines.slice(1)
.filter(line => line.trim() !== '')
.map(line => {
const values = line.split(',')
return Object.fromEntries(
headers.map((header, i) => [
header,
coerce ? coerceValue(values[i]?.trim()) : values[i]?.trim()
])
)
})
return JSON.stringify(rows, null, 2)
}
const csv = `endpoint,port,max_connections,debug
/api/v2/orders,8443,500,true
/api/v2/health,8080,100,false`
console.log(csvToJson(csv, { coerce: true }))
// [
// { "endpoint": "/api/v2/orders", "port": 8443, "max_connections": 500, "debug": true },
// { "endpoint": "/api/v2/health", "port": 8080, "max_connections": 100, "debug": false }
// ]Il flag coerce è opt-in perché il rilevamento automatico dei tipi può dare risultati indesiderati — un campo come un codice postale ("20121") perde gli zeri iniziali quando viene convertito in numero. Mantieni la coercizione disabilitata per default e abilitala solo quando controlli lo schema. Nota rapida: JSON.stringify() accetta un terzo argomento space per il rientro. Passa 2 per due spazi, 4 per quattro, o "\t" per le tabulazioni. Omettilo del tutto per un output compatto su una sola riga — utile quando invii la stringa JSON come corpo di una richiesta API dove gli spazi sprecano solo banda.
JSON.parse() direttamente sul testo CSV genera un SyntaxError. Devi prima convertire il CSV in oggetti JavaScript con la tua funzione csvToJson(), che internamente chiama JSON.stringify() per produrre la stringa JSON effettiva.Gestire Map, Date e Oggetti Personalizzati dai Dati CSV
Non ogni conversione CSV termina con un array flat di oggetti semplici. A volte devi costruire una Map da coppie intestazione-valore, analizzare stringhe di data in oggetti Date, o aggiungere proprietà calcolate prima della serializzazione. JavaScript ha una particolarità che inganna molti: le istanze di Map non si serializzano con JSON.stringify(). Ottieni un oggetto vuoto. La soluzione è Object.fromEntries() per convertire la Map in un oggetto semplice prima di stringificarla.
Il motivo per cui Map si serializza come {} è che JSON.stringify() itera sulle proprietà enumerabili proprie di un oggetto. Una Map memorizza le sue voci in uno slot interno, non come proprietà enumerabili sull'oggetto stesso, quindi il serializzatore vede un oggetto senza chiavi. Il prototipo di Map manca anche di un metodo toJSON(), che è il gancio che JSON.stringify() chiama per primo su qualsiasi valore prima di decidere come serializzarlo. Se un valore ha toJSON(), il valore restituito dal metodo è ciò che viene serializzato — non l'oggetto stesso. Ecco perché gli oggetti Date si serializzano correttamente: Date.prototype.toJSON restituisce una stringa ISO 8601, quindi JSON.stringify(new Date()) produce un timestamp tra virgolette invece di un oggetto vuoto. Comprendere questo gancio ti permette di definire lo stesso comportamento nelle tue classi — come mostrato nell'esempio EmployeeRecord qui sotto — per controllare esattamente quali campi derivati dal CSV compaiono nell'output JSON finale.
Conversione di una Map in JSON
// Costruire una Map da coppie intestazione→valore CSV
const headers = ['server', 'port', 'region']
const values = ['payments-api', '9090', 'ap-south-1']
const rowMap = new Map(headers.map((h, i) => [h, values[i]]))
// Map NON si serializza direttamente
console.log(JSON.stringify(rowMap))
// "{}" — oggetto vuoto, dati persi!
// Converti prima in oggetto semplice
const rowObj = Object.fromEntries(rowMap)
console.log(JSON.stringify(rowObj, null, 2))
// {
// "server": "payments-api",
// "port": "9090",
// "region": "ap-south-1"
// }Stringhe Date e toJSON()
I campi data nel CSV arrivano come stringhe. Se li analizzi in oggetti Date durante l'elaborazione, queste Date si serializzano correttamente perché Date ha un metodo toJSON() integrato che restituisce una stringa ISO 8601. Puoi anche definire toJSON() personalizzato nelle tue classi per controllare quali colonne CSV compaiono nell'output serializzato — ad esempio, omettendo campi di tracciamento interni come _rowIndex.
class EmployeeRecord {
constructor(csvRow) {
this._rowIndex = csvRow._rowIndex // interno, non per JSON
this.employeeId = csvRow.employee_id
this.name = csvRow.name
this.hiredAt = new Date(csvRow.hired_date)
this.salary = Number(csvRow.salary)
}
toJSON() {
// Esponi solo i campi che vogliamo nell'output JSON
return {
employee_id: this.employeeId,
name: this.name,
hired_at: this.hiredAt, // Date.toJSON() → stringa ISO automaticamente
salary: this.salary,
}
}
}
const csvRow = {
_rowIndex: 42,
employee_id: 'EMP-2847',
name: 'Marco Rossi',
hired_date: '2024-03-15',
salary: '128000',
}
const record = new EmployeeRecord(csvRow)
console.log(JSON.stringify(record, null, 2))
// {
// "employee_id": "EMP-2847",
// "name": "Marco Rossi",
// "hired_at": "2024-03-15T00:00:00.000Z",
// "salary": 128000
// }
// Nota: _rowIndex è escluso, salary è un numero, la data è in formato ISOReviver per la Deserializzazione delle Date
Dopo aver scritto JSON derivato da CSV su un file o averlo inviato in rete, JSON.parse() restituisce oggetti semplici — gli oggetti Date tornano ad essere stringhe. Usa una funzione reviver per riconvertire le stringhe ISO 8601 in oggetti Date durante il parsing:
const jsonString = '{"employee_id":"EMP-2847","name":"Marco Rossi","hired_at":"2024-03-15T00:00:00.000Z","salary":128000}'
const isoDatePattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/
const parsed = JSON.parse(jsonString, (key, value) => {
if (typeof value === 'string' && isoDatePattern.test(value)) {
return new Date(value)
}
return value
})
console.log(parsed.hired_at instanceof Date) // true
console.log(parsed.hired_at.getFullYear()) // 2024JSON.stringify() restituisce undefined (non una stringa) per valori che contengono funzioni, Symbol o proprietà undefined. Se i tuoi oggetti derivati da CSV raccolgono accidentalmente un valore undefined da una colonna mancante, quella proprietà sparisce silenziosamente dall'output JSON. Usa sempre null come valore predefinito per i valori mancanti.Riferimento Parametri di JSON.stringify()
La firma della funzione è JSON.stringify(value, replacer?, space?). Gli argomenti replacer e space sono entrambi facoltativi — passa null per il replacer quando hai bisogno solo del rientro.
Parametri di JSON.parse():
JSON.parse() — Consumare l'Output JSON
Una volta ottenuta una stringa JSON da csvToJson(), il passaggio successivo è di solito analizzarla di nuovo in un array JavaScript attivo per filtrare, mappare o passare a un'API. La differenza tra una stringa JSON (typeof === "string") e un oggetto JavaScript è importante. Non puoi chiamare .filter() o accedere a [0].nome su una stringa — hai bisogno di JSON.parse() prima. Questo ciclo completo (stringify poi parse) funziona anche come tecnica di validazione: se la tua conversione CSV ha prodotto qualcosa che non è JSON valido, parse genera un errore. L'argomento opzionale reviver ti permette di trasformare ogni coppia chiave-valore durante il parsing — utile per ripristinare oggetti Date da stringhe ISO o rinominare chiavi senza un passaggio separato.
const csv = `endpoint,method,avg_latency_ms,error_rate
/api/v2/orders,POST,342,0.02
/api/v2/health,GET,12,0.00
/api/v2/payments,POST,890,0.15
/api/v2/users,GET,45,0.01`
// Passo 1: converti CSV in stringa JSON
const jsonString = csvToJson(csv, { coerce: true })
// Passo 2: analizza di nuovo in array JavaScript
const endpoints = JSON.parse(jsonString)
// Verifica che sia un array
console.log(Array.isArray(endpoints)) // true
// Filtra gli endpoint ad alta latenza
const slow = endpoints.filter(ep => ep.avg_latency_ms > 200)
console.log(slow.map(ep => ep.endpoint))
// ["/api/v2/orders", "/api/v2/payments"]
// Destruttura la prima riga
const [first, ...rest] = endpoints
console.log(first.endpoint) // "/api/v2/orders"
console.log(rest.length) // 3Un wrapper sicuro per JSON.parse() è utile per validare l'output della conversione prima dell'elaborazione a valle. Se la conversione CSV produce JSON malformato per qualsiasi motivo (input troncato, errori di codifica), questo lo intercetta senza crash:
function safeParse(jsonString) {
try {
return { data: JSON.parse(jsonString), error: null }
} catch (err) {
return { data: null, error: err.message }
}
}
// Output valido
const result = safeParse(csvToJson(csv))
if (result.error) {
console.error('La conversione CSV ha prodotto JSON non valido:', result.error)
} else {
console.log(`Analizzate ${result.data.length} righe`)
}
// Passaggio accidentale di CSV grezzo a JSON.parse — questo fallisce
const bad = safeParse('nome,email\nMarco,mrossi@nexuslabs.io')
console.log(bad.error) // "Unexpected token 'a', "nome,email"... is not valid JSON"Reviver per Rinominare Chiavi e Validazione
La funzione reviver riceve ogni coppia chiave-valore durante il parsing, dalle proprietà più interne verso l'esterno. Restituire undefined per una chiave la rimuove completamente dal risultato; restituire un valore diverso la sostituisce. Il reviver è utile per rinominare le intestazioni (da camelCase a snake_case), rimuovere campi interni, o verificare l'esistenza delle colonne obbligatorie. Viene chiamato con il valore radice per ultimo (chiave stringa vuota), che è dove puoi generare un errore se il risultato non è un array.
const jsonString = csvToJson(`employeeId,firstName,hiredDate
EMP-2847,Marco,2024-03-15
EMP-3012,Giulia,2023-11-01`, { coerce: false })
const camelToSnake = str => str.replace(/[A-Z]/g, c => '_' + c.toLowerCase())
const employees = JSON.parse(jsonString, function(key, value) {
// Valore radice — valida la struttura
if (key === '') {
if (!Array.isArray(value)) throw new Error('Atteso array JSON dal CSV')
return value
}
// Rinomina le chiavi camelCase delle intestazioni in snake_case
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
return Object.fromEntries(
Object.entries(value).map(([k, v]) => [camelToSnake(k), v])
)
}
return value
})
console.log(employees[0])
// { employee_id: 'EMP-2847', first_name: 'Marco', hired_date: '2024-03-15' }Converti CSV da File e Risposta API
I due posti da cui i dati CSV arrivano effettivamente in produzione: file su disco e risposte HTTP. Entrambi gli scenari richiedono la gestione degli errori perché l'input è esterno e non controllato.
Leggi File CSV, Converti, Scrivi JSON
import { readFileSync, writeFileSync } from 'node:fs'
function csvToJsonFromFile(inputPath, outputPath) {
let csvText
try {
csvText = readFileSync(inputPath, 'utf8')
} catch (err) {
throw new Error(`Impossibile leggere ${inputPath}: ${err.message}`)
}
const lines = csvText.trim().split('\n')
if (lines.length < 2) {
throw new Error(`${inputPath} non ha righe di dati (solo ${lines.length} riga)`)
}
const headers = lines[0].split(',').map(h => h.trim())
const rows = lines.slice(1)
.filter(line => line.trim() !== '')
.map(line => {
const values = line.split(',')
return Object.fromEntries(headers.map((h, i) => [h, values[i]?.trim()]))
})
const jsonOutput = JSON.stringify(rows, null, 2)
writeFileSync(outputPath, jsonOutput, 'utf8')
console.log(`Convertite ${rows.length} righe → ${outputPath}`)
return rows
}
// Utilizzo
const data = csvToJsonFromFile('inventario.csv', 'inventario.json')
console.log(data[0])
// { sku: "WDG-2847", warehouse: "us-east-1", quantity: "150", ... }Recupera CSV da un Endpoint API
async function fetchCsvAsJson(url) {
const response = await fetch(url)
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
const contentType = response.headers.get('content-type') || ''
if (!contentType.includes('text/csv') && !contentType.includes('text/plain')) {
console.warn(`Content-type inatteso: ${contentType}`)
}
const csvText = await response.text()
const lines = csvText.trim().split('\n')
const headers = lines[0].split(',').map(h => h.trim())
const rows = lines.slice(1)
.filter(line => line.trim() !== '')
.map(line => {
const values = line.split(',')
return Object.fromEntries(headers.map((h, i) => [h, values[i]?.trim()]))
})
return rows
}
// Esempio: recupera CSV dei tassi di cambio da un fornitore di dati
try {
const rates = await fetchCsvAsJson('https://data.ecb.internal/rates/daily.csv')
console.log(JSON.stringify(rates.slice(0, 3), null, 2))
// Invia come JSON al servizio a valle
await fetch('https://api.internal/v2/rates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ data: rates }),
})
} catch (err) {
console.error('Sincronizzazione tassi fallita:', err.message)
}JSON.stringify() ti permette di specificare esattamente le colonne CSV da includere. Passa un array di nomi di intestazione per includere solo quei campi: JSON.stringify(rows, ['nome', 'email', 'reparto']). Le proprietà non presenti nell'array vengono silenziosamente escluse dall'output.Conversione CSV in JSON da Riga di Comando
Node.js può eseguire script inline, e ci sono strumenti CLI dedicati che gestiscono la conversione CSV-to-JSON senza scrivere uno script.
# Pipe CSV a uno script inline Node.js
cat servers.csv | node -e "
const lines = require('fs').readFileSync('/dev/stdin','utf8').trim().split('\n');
const h = lines[0].split(',');
const rows = lines.slice(1).map(l => Object.fromEntries(h.map((k,i) => [k.trim(), l.split(',')[i]?.trim()])));
console.log(JSON.stringify(rows, null, 2));
"# Miller è un coltellino svizzero per dati strutturati # Installa: brew install miller (macOS) o apt install miller (Debian/Ubuntu) mlr --icsv --ojson cat inventario.csv # Filtra righe durante la conversione mlr --icsv --ojson filter '$quantity > 100' inventario.csv # Seleziona colonne specifiche mlr --icsv --ojson cut -f sku,warehouse,quantity inventario.csv
# Installa globalmente npm install -g csvtojson # Converti file csvtojson servers.csv > servers.json # Pipe da stdin cat exports/q1-metrics.csv | csvtojson > q1-metrics.json
Per file di grandi dimensioni, Miller è generalmente la scelta migliore rispetto a csvtojson. Miller è implementato in C e processa il CSV come stream senza caricare l'intero file in memoria, il che significa che gestisce export multi-gigabyte con utilizzo di memoria costante. Supporta anche operazioni a livello di campo in-place — rinominare colonne, convertire i tipi dei valori, filtrare righe — prima che i dati diventino JSON, così eviti una pipeline in due fasi di parse-poi-trasforma. csvtojson, d'altra parte, gira su Node.js ed è più comodo quando il resto della tua toolchain è in JavaScript: puoi collegare il suo output direttamente a stream Node.js, importarlo come libreria, o usare la sua API colParser per la coercizione dei tipi per colonna nel codice. Preferisci Miller per la massima velocità e le pipeline shell; preferisci csvtojson quando hai bisogno di un'integrazione stretta con un'applicazione Node.js.
jq non analizza il CSV nativamente. Se hai bisogno di jq nella pipeline, converti prima in JSON con csvtojson o mlr, poi invia l'output JSON a jq per filtrare e trasformare.Alternativa ad Alto Rendimento — PapaParse
L'approccio manuale con split(',') fallisce su file CSV reali. Campi tra virgolette contenenti virgole, newline incorporati, virgolette doppie di escape — tutto questo rompe uno splitter ingenuo. PapaParse è la libreria a cui ricorro quando il CSV proviene da una fonte sconosciuta. Gestisce ogni caso limite di RFC 4180, rileva automaticamente i delimitatori, e funziona sia in Node.js che nei browser.
npm install papaparse
import Papa from 'papaparse'
const csv = `prodotto,descrizione,prezzo,disponibile
"Widget, Grande","Un widget premium con funzionalità ""extra""",29.99,true
Kit Bulloni,Kit bulloni M8 standard,4.50,true
"Set Guarnizioni","Include guarnizione, tenuta e O-ring",12.75,false`
const { data, errors, meta } = Papa.parse(csv, {
header: true,
dynamicTyping: true, // converte automaticamente numeri e booleani
skipEmptyLines: true,
transformHeader: h => h.trim().toLowerCase().replace(/\s+/g, '_'),
})
if (errors.length > 0) {
console.error('Errori di parsing:', errors)
}
console.log(JSON.stringify(data, null, 2))
// [
// {
// "prodotto": "Widget, Grande",
// "descrizione": "Un widget premium con funzionalità \"extra\"",
// "prezzo": 29.99,
// "disponibile": true
// },
// ...
// ]
console.log(`Analizzate ${data.length} righe, delimitatore: "${meta.delimiter}"`)L'opzione dynamicTyping di PapaParse esegue la coercizione dei tipi automaticamente — i numeri diventano numeri, "true"/"false" diventano booleani. Il callback transformHeader normalizza i nomi delle colonne in snake_case, risparmiandoti di gestire intestazioni inconsistenti da diversi export CSV. Per conversioni rapide senza scrivere alcun codice di parsing, il convertitore CSV in JSON gestisce tutto nel browser.
Output nel Terminale con Syntax Highlighting
Scaricare un grande array JSON nel terminale può rendere la lettura molto faticosa. Aggiungere syntax highlighting all'output lo rende leggibile durante il debug e lo sviluppo. Il pacchetto cli-highlight colorizza l'output JSON nei terminali Node.js.
npm install cli-highlight
import { highlight } from 'cli-highlight'
// Dopo la conversione da CSV a array JSON
const jsonOutput = JSON.stringify(rows, null, 2)
// Stampa con syntax highlighting
console.log(highlight(jsonOutput, { language: 'json' }))
// Chiavi, stringhe, numeri e booleani ricevono colori distintiL'output colorizzato si rivela utile quando stai ispezionando interattivamente un grande risultato di conversione. Le chiavi JSON, i valori stringa, i numeri e i booleani ricevono colori ANSI distinti, il che rende facile individuare un campo il cui tipo è sbagliato — ad esempio, un numero di porta che dovrebbe essere 8080 ma è evidenziato come stringa perché la coercizione era disabilitata. Questo è particolarmente utile quando si eseguono debug su file CSV esportati da strumenti di foglio di calcolo dove i tipi delle colonne sono inconsistenti tra le righe. Senza colore, scansionare 50 righe di JSON alla ricerca di un singolo campo con tipo errato significa leggere ogni valore individualmente. Con il colore, un numero evidenziato come stringa salta all'occhio immediatamente.
Lavorare con File CSV di Grandi Dimensioni
Caricare un file CSV da 500 MB in una stringa con readFileSync() consumerà molta memoria e potenzialmente causerà il crash del processo. Per file di grandi dimensioni, elabora il CSV riga per riga come stream ed emetti oggetti JSON man mano che arrivano. Il pacchetto csv-parse (parte dell'ecosistema csv su npm) fornisce un parser in streaming che funziona con i stream Node.js.
Streaming CSV in NDJSON con csv-parse
NDJSON (Newline-Delimited JSON) è un formato in cui ogni riga del file di output è un oggetto JSON autonomo. A differenza di un singolo grande array JSON — che richiede l'intero file in memoria prima di poter iniziare a leggerlo — i file NDJSON possono essere elaborati riga per riga. Questo rende NDJSON ideale per dataset di grandi dimensioni che verranno consumati da processori di log, pipeline di stream, o database con API di importazione bulk. Il pacchetto csv-parse emette un oggetto JavaScript per ogni riga CSV in modalità oggetto, quindi puoi inviarlo in pipe direttamente a un transform stream che aggiunge \n dopo ogni JSON.stringify(row).
import { createReadStream, createWriteStream } from 'node:fs'
import { parse } from 'csv-parse'
import { Transform } from 'node:stream'
import { pipeline } from 'node:stream/promises'
// Trasforma ogni oggetto riga CSV in una riga JSON
const toNdjson = new Transform({
objectMode: true,
transform(record, encoding, callback) {
callback(null, JSON.stringify(record) + '\n')
},
})
await pipeline(
createReadStream('telemetry-2026-03.csv'),
parse({
columns: true, // usa la prima riga come intestazioni
skip_empty_lines: true,
trim: true,
cast: true, // converti automaticamente numeri e booleani
}),
toNdjson,
createWriteStream('telemetry-2026-03.ndjson')
)
console.log('Conversione in streaming completata')
// Ogni riga nel file di output è un oggetto JSON:
// {"timestamp":"2026-03-15T08:22:00Z","service":"gateway","latency_ms":42,"status":200}
// {"timestamp":"2026-03-15T08:22:01Z","service":"auth","latency_ms":156,"status":401}
// ...Streaming PapaParse per Browser e Node.js
La modalità streaming di PapaParse usa un callback step che si attiva una volta per riga invece di raccogliere tutte le righe in memoria. Gli passi un Node.js ReadStream (in Node.js) o un oggetto File (nel browser) e PapaParse gestisce internamente il chunking. Nessuna pipeline di stream da configurare — solo un callback. Usalo quando hai bisogno della conformità RFC 4180 senza includere csv-parse.
import Papa from 'papaparse'
import { createReadStream } from 'node:fs'
let rowCount = 0
const errors = []
const fileStream = createReadStream('warehouse-inventory.csv')
Papa.parse(fileStream, {
header: true,
dynamicTyping: true,
step(result) {
// Elabora una riga alla volta — memoria costante
rowCount++
if (result.data.quantity === 0) {
errors.push(`Riga ${rowCount}: ${result.data.sku} è esaurito`)
}
},
complete() {
console.log(`Elaborate ${rowCount} righe`)
if (errors.length > 0) {
console.log(`Problemi trovati: ${errors.length}`)
errors.forEach(e => console.log(` ${e}`))
}
},
error(err) {
console.error('Parsing fallito:', err.message)
},
})Errori Comuni
Problema: Il CSV non è JSON. Passare una stringa CSV grezza a JSON.parse() genera un SyntaxError perché le virgole e i newline non sono sintassi JSON valida.
Soluzione: Analizza prima il CSV in oggetti JavaScript usando split() o una libreria, poi usa JSON.stringify() per produrre JSON. Chiama JSON.parse() solo su stringhe che sono già JSON valido.
const csv = 'nome,email\nMarco Rossi,mrossi@nexuslabs.io' const data = JSON.parse(csv) // SyntaxError: Unexpected token 'a'
const csv = 'nome,email\nMarco Rossi,mrossi@nexuslabs.io'
const lines = csv.trim().split('\n')
const headers = lines[0].split(',')
const rows = lines.slice(1).map(line =>
Object.fromEntries(headers.map((h, i) => [h, line.split(',')[i]]))
)
const json = JSON.stringify(rows, null, 2) // stringa JSON validaProblema: Chiamare toString() su un oggetto JavaScript restituisce la stringa inutile '[object Object]' invece dei dati effettivi. Questo distrugge silenziosamente il tuo output CSV-to-JSON.
Soluzione: Usa sempre JSON.stringify() per convertire oggetti JavaScript in stringhe JSON. toString() esiste per la coercizione da primitivo a stringa, non per la serializzazione.
const row = { server: 'api-gateway', port: 8080 }
const output = row.toString()
// "[object Object]" — i dati sono persiconst row = { server: 'api-gateway', port: 8080 }
const output = JSON.stringify(row, null, 2)
// '{"server":"api-gateway","port":8080}'Problema: Un semplice split(",") si rompe quando i valori CSV contengono virgole all'interno di campi tra virgolette: "Widget, Grande" diventa due valori separati invece di uno.
Soluzione: Usa PapaParse o csv-parse per qualsiasi dato CSV che non controlli completamente. Se devi analizzare manualmente, implementa un parser a macchina a stati che tiene traccia se la posizione corrente è all'interno di un campo tra virgolette.
const line = '"Widget, Grande","Qualità premium",29.99'
const values = line.split(',')
// ["\"Widget", " Grande\"", "\"Qualità premium\"", "29.99"]
// 4 valori invece di 3 — primo campo diviso in modo erratoimport Papa from 'papaparse'
const { data } = Papa.parse('"Widget, Grande","Qualità premium",29.99')
// data[0] = ["Widget, Grande", "Qualità premium", "29.99"]
// 3 valori, analizzati correttamenteProblema: Senza coercizione dei tipi, port: "8080" rimane una stringa in JSON invece di un numero. I sistemi a valle che si aspettano tipi numerici rifiutano o gestiscono male i dati.
Soluzione: Applica una coercizione esplicita dei tipi durante la fase di mappatura, oppure usa PapaParse con dynamicTyping: true. Sii sempre deliberato riguardo a quali campi devono essere numerici.
const row = { port: '8443', debug: 'true', workers: '4' }
JSON.stringify(row)
// {"port":"8443","debug":"true","workers":"4"} — tutte stringheconst row = {
port: Number('8443'), // 8443
debug: 'true' === 'true', // true
workers: Number('4'), // 4
}
JSON.stringify(row)
// {"port":8443,"debug":true,"workers":4} — tipi correttiParsing Manuale vs Librerie — Confronto Rapido
Per script veloci dove controlli il formato CSV e sai che non ci sono campi tra virgolette, l'approccio integrato con split() + JSON.stringify() funziona e richiede zero dipendenze. Per sistemi di produzione che elaborano file CSV caricati dagli utenti, usa PapaParse nel browser o csv-parse in Node.js — entrambi gestiscono RFC 4180 correttamente e supportano lo streaming. Il pacchetto csvtojson è l'unico che produce JSON direttamente, gestendo sia il parsing che la serializzazione in una singola chiamata. Quando hai bisogno del percorso più veloce da incolla-al-risultato, il convertitore CSV in JSON gestisce tutto nel browser senza alcuna configurazione.
Domande Frequenti
Come si converte CSV in JSON in JavaScript senza una libreria?
Dividi la stringa CSV per newline per ottenere le righe, estrai le intestazioni dalla prima riga con split(","), poi mappa le righe rimanenti su oggetti con chiavi prese dalle intestazioni. Concludi con JSON.stringify(array, null, 2) per produrre una stringa JSON formattata. Questo approccio funziona bene per file CSV semplici in cui controlli il formato e sai che non ci sono campi tra virgolette o virgole incorporate. Per dati provenienti da export di fogli di calcolo o sistemi di terze parti, i campi tra virgolette e i valori su più righe romperanno uno splitter ingenuo — passa a PapaParse o csv-parse in quei casi. Per file molto piccoli elaborati nel browser, questo approccio senza dipendenze è ideale.
const csv = `nome,email,reparto
Marco Rossi,mrossi@nexuslabs.io,Ingegneria
Giulia Ferrari,gferrari@nexuslabs.io,Prodotto`
const lines = csv.trim().split('\n')
const headers = lines[0].split(',')
const rows = lines.slice(1).map(line => {
const values = line.split(',')
return Object.fromEntries(headers.map((h, i) => [h.trim(), values[i]?.trim()]))
})
console.log(JSON.stringify(rows, null, 2))
// [
// { "nome": "Marco Rossi", "email": "mrossi@nexuslabs.io", "reparto": "Ingegneria" },
// { "nome": "Giulia Ferrari", "email": "gferrari@nexuslabs.io", "reparto": "Prodotto" }
// ]Qual è la differenza tra JSON.stringify() e toString() per gli oggetti?
toString() su un oggetto semplice restituisce la stringa inutile "[object Object]" — non dice nulla sui dati effettivi. JSON.stringify() produce una stringa JSON valida con tutte le chiavi e i valori correttamente serializzati, inclusi oggetti e array annidati. Usa sempre JSON.stringify() quando devi convertire un oggetto JavaScript (come una riga derivata da un CSV) in una stringa JSON. Per invertire l'operazione — ricostruire oggetti JavaScript attivi da una stringa JSON — usa JSON.parse(), che è l'esatto inverso di JSON.stringify(). Queste due funzioni formano un ciclo completo: stringify per persistere o trasmettere i dati, parse per consumarli.
const row = { nome: 'Marco Rossi', ruolo: 'Ingegnere' }
console.log(row.toString()) // "[object Object]"
console.log(JSON.stringify(row)) // '{"nome":"Marco Rossi","ruolo":"Ingegnere"}'Come gestire i campi CSV che contengono virgole o virgolette?
RFC 4180 specifica che i campi contenenti virgole, newline o virgolette doppie devono essere racchiusi tra virgolette doppie, con le virgolette incorporate che vengono raddoppiate ("" all'interno di un campo tra virgolette rappresenta una singola virgoletta letterale). Un semplice split(",") si rompe su questi file — il confine del campo non è più una semplice virgola. Usa PapaParse o csv-parse per dati di produzione, oppure scrivi un parser a macchina a stati che tiene traccia se ti trovi all'interno di un campo tra virgolette. Scrivere una macchina a stati corretta da zero è sorprendentemente complicato: devi gestire le virgolette all'inizio di un campo, le virgolette di escape nel mezzo del campo, i newline all'interno dei campi tra virgolette, e le diverse convenzioni di fine riga (CRLF vs LF). Per qualsiasi cosa al di là di dati CSV di prova, usa una libreria ben testata.
// PapaParse gestisce RFC 4180 correttamente
import Papa from 'papaparse'
const csv = `prodotto,descrizione,prezzo
"Widget, Grande","Un grande ""widget""",29.99
Bullone,Bullone standard,1.50`
const { data } = Papa.parse(csv, { header: true })
console.log(JSON.stringify(data, null, 2))
// il campo descrizione contiene correttamente: Un grande "widget"Posso convertire CSV in JSON direttamente nel browser?
Sì. Sia JSON.stringify() che JSON.parse() sono integrati in ogni motore browser. Per la fase di parsing del CSV, puoi dividere per newline e virgola per file semplici, oppure includere PapaParse tramite CDN (non ha dipendenze da Node.js). L'intera conversione avviene lato client senza alcun round-trip al server, il che è utile per la privacy dei file — i dati CSV grezzi non lasciano mai la macchina dell'utente. Quando un utente carica un file CSV tramite un elemento <input type="file">, il metodo file.text() della File API restituisce una Promise che si risolve con il contenuto del file come stringa, che puoi poi passare alla tua funzione di conversione. Questo rende la conversione CSV-to-JSON completamente nel browser pratica per dashboard, strumenti per sviluppatori e qualsiasi app che debba elaborare dati caricati senza un backend.
// Browser: l'utente carica un file CSV
const fileInput = document.querySelector('input[type="file"]')
fileInput.addEventListener('change', async (event) => {
const file = event.target.files[0]
const text = await file.text()
const lines = text.trim().split('\n')
const headers = lines[0].split(',')
const rows = lines.slice(1).map(line =>
Object.fromEntries(headers.map((h, i) => [h.trim(), line.split(',')[i]?.trim()]))
)
console.log(JSON.stringify(rows, null, 2))
})Come analizzare valori numerici e booleani da CSV invece di mantenere tutto come stringhe?
Il CSV non ha un sistema di tipi — ogni campo è una stringa. Devi forzare i valori durante la fase di mappatura. Controlla i pattern numerici con Number() o parseFloat(), converti "true"/"false" in booleani, e gestisci le stringhe vuote come null. Fai attenzione ai campi che sembrano numeri ma devono rimanere come stringhe: i codici di avviamento postale come "20121" perdono gli zeri iniziali quando vengono convertiti con Number(), e i numeri di telefono o i codici prodotto con caratteri numerici sono ugualmente fragili. La libreria csvtojson esegue la coercizione automatica dei tipi tramite la sua opzione colParser, che ti permette di specificare funzioni di conversione per colonna e sovrascrivere il rilevamento automatico per le colonne problematiche. L'opzione dynamicTyping di PapaParse applica la stessa coercizione globalmente su tutte le colonne.
function coerceValue(val) {
if (val === '') return null
if (val === 'true') return true
if (val === 'false') return false
const num = Number(val)
if (!isNaN(num) && val.trim() !== '') return num
return val
}
// Applicare durante la mappatura CSV-to-object
const row = { port: coerceValue('8443'), debug: coerceValue('true'), host: coerceValue('api.internal') }
// { port: 8443, debug: true, host: "api.internal" }Come scrivere l'output CSV-to-JSON su un file in Node.js?
Usa fs.writeFileSync() con l'output di JSON.stringify(). Il terzo argomento di JSON.stringify controlla il rientro — passa 2 per due spazi o "\t" per le tabulazioni. Per rileggere il file, usa JSON.parse(fs.readFileSync(path, "utf8")), che ricostruisce l'array JavaScript attivo di oggetti. Se stai scrivendo il file in un contesto asincrono (all'interno di una funzione async o al top level di un modulo ES), preferisci fs.promises.writeFile() per evitare di bloccare il ciclo degli eventi durante la scrittura del file. Per output JSON di grandi dimensioni oltre qualche megabyte, considera di inviare in pipe un flusso JSON a un WriteStream invece di costruire l'intera stringa in memoria prima di scrivere.
import { writeFileSync, readFileSync } from 'node:fs'
// Scrittura
const jsonOutput = JSON.stringify(rows, null, 2)
writeFileSync('dipendenti.json', jsonOutput, 'utf8')
// Rilettura
const parsed = JSON.parse(readFileSync('dipendenti.json', 'utf8'))
console.log(Array.isArray(parsed)) // true
console.log(parsed[0].nome) // "Marco Rossi"Strumenti Correlati
Alex is a front-end and Node.js developer with extensive experience building web applications and developer tooling. He is passionate about web standards, browser APIs, and the JavaScript ecosystem. In his spare time he contributes to open-source projects and writes about modern JavaScript patterns, performance optimisation, and everything related to the web platform.
Sophie is a full-stack developer focused on TypeScript across the entire stack — from React frontends to Express and Fastify backends. She has a particular interest in type-safe API design, runtime validation, and the patterns that make large JavaScript codebases stay manageable. She writes about TypeScript idioms, Node.js internals, and the ever-evolving JavaScript module ecosystem.