CSV to JSON JavaScript — Converter + Code Examples

·Front-end & Node.js Developer·Revisionato daSophie Laurent·Pubblicato

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.

Before · json
After · json
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:

JavaScript — csvToJson minimale
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:

JavaScript — csvToJson con coercizione 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.

Nota:Una stringa CSV grezza non è JSON. Chiamare 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

JavaScript — Map in JSON via Object.fromEntries()
// 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.

JavaScript — toJSON() per serializzazione personalizzata
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 ISO

Reviver 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:

JavaScript — reviver per ricostruire oggetti Date
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())    // 2024
Attenzione:JSON.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.

Parametro
Tipo
Predefinito
Descrizione
value
any
(obbligatorio)
Il valore JavaScript da serializzare — oggetto, array, stringa, numero, booleano o null
replacer
Function | Array | null
undefined
Filtra o trasforma i valori durante la serializzazione. Un array indica i nomi delle proprietà da includere; una funzione riceve coppie (key, value)
space
number | string
undefined
Indentazione: numero 0–10 per gli spazi, stringa (es. "\t") per un rientro personalizzato. Ometti per un output compatto su una sola riga

Parametri di JSON.parse():

Parametro
Tipo
Predefinito
Descrizione
text
string
(obbligatorio)
La stringa JSON da analizzare — deve essere JSON valido o viene generato un SyntaxError
reviver
Function | undefined
undefined
Chiamata per ogni coppia chiave-valore. Il valore restituito sostituisce l'originale; restituire undefined elimina la proprietà

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.

JavaScript — analizza l'output JSON e interroga le righe
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)     // 3

Un 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:

JavaScript — wrapper di parse sicuro
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.

JavaScript — reviver per rinominare chiavi e validare la struttura
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

Node.js 18+ — conversione da file
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

Node.js 18+ — conversione risposta 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)
}
Nota:L'argomento replacer in 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.

bash — Node.js one-liner
# 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));
"
bash — Miller (mlr) per CSV in JSON
# 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
bash — csvtojson CLI
# 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.

Nota: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.

bash — installa PapaParse
npm install papaparse
JavaScript — PapaParse con coercizione dei tipi
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.

bash — installa cli-highlight
npm install cli-highlight
JavaScript — output JSON colorizzato nel terminale
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 distinti

L'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.

Attenzione:Il syntax highlighting aggiunge codici di escape ANSI all'output. Non usarlo quando scrivi JSON su un file, lo invii in pipe a un altro programma, o lo mandi come corpo di una risposta API — i codici di escape corromperebbero il JSON. Usa l'highlighting solo per la visualizzazione nel terminale.

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).

Node.js 18+ — streaming CSV in NDJSON
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.

Node.js — PapaParse streaming file di grandi dimensioni
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)
  },
})
Nota:Passa allo streaming quando il tuo file CSV supera i 50 MB o quando stai elaborando un input illimitato (feed WebSocket, server-sent events, stdin in pipe). Il formato NDJSON (un oggetto JSON per riga) è spesso un formato di output migliore rispetto a un enorme array JSON per dataset di grandi dimensioni — può essere elaborato riga per riga senza caricare l'intero file in memoria.

Errori Comuni

Chiamare JSON.parse() direttamente su una stringa CSV

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.

Before · JavaScript
After · JavaScript
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 valida
Usare toString() invece di JSON.stringify()

Problema: 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.

Before · JavaScript
After · JavaScript
const row = { server: 'api-gateway', port: 8080 }
const output = row.toString()
// "[object Object]"  — i dati sono persi
const row = { server: 'api-gateway', port: 8080 }
const output = JSON.stringify(row, null, 2)
// '{"server":"api-gateway","port":8080}'
Dividere sulla virgola senza gestire i campi tra virgolette

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.

Before · JavaScript
After · JavaScript
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 errato
import Papa from 'papaparse'
const { data } = Papa.parse('"Widget, Grande","Qualità premium",29.99')
// data[0] = ["Widget, Grande", "Qualità premium", "29.99"]
// 3 valori, analizzati correttamente
Dimenticare che tutti i valori CSV sono stringhe

Problema: 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.

Before · JavaScript
After · JavaScript
const row = { port: '8443', debug: 'true', workers: '4' }
JSON.stringify(row)
// {"port":"8443","debug":"true","workers":"4"}  — tutte stringhe
const row = {
  port: Number('8443'),           // 8443
  debug: 'true' === 'true',      // true
  workers: Number('4'),           // 4
}
JSON.stringify(row)
// {"port":8443,"debug":true,"workers":4}  — tipi corretti

Parsing Manuale vs Librerie — Confronto Rapido

Metodo
Output formattato
JSON valido
Tipi personalizzati
Streaming
Richiede installazione
JSON.stringify()
✓ (con space)
✓ via toJSON()/replacer
No (integrato)
JSON.parse()
N/A (parsing)
✓ (valida)
✓ via reviver
No (integrato)
csv-parse (Node.js)
✗ (restituisce oggetti)
✗ (non è JSON)
npm install
PapaParse
✗ (restituisce oggetti)
✗ (non è JSON)
npm install
csvtojson
✓ via colParser
npm install
jq (CLI)
N/A
Installazione di sistema
Miller (CLI)
N/A
Installazione di sistema

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.

JavaScript
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.

JavaScript
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.

JavaScript
// 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.

JavaScript
// 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.

JavaScript
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.

JavaScript
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

Disponibile anche in:Python
AC
Alex ChenFront-end & Node.js Developer

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.

SL
Sophie LaurentRevisore tecnico

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.