CSV to JSON JavaScript โ€” Converter + Code Examples

ยทFront-end & Node.js DeveloperยทDitinjau olehSophie LaurentยทDiterbitkan

Gunakan CSV to JSON gratis langsung di browser Anda โ€” tidak perlu instalasi.

Coba CSV to JSON Online โ†’

Sebagian besar data CSV yang saya temui datang sebagai string datar dari unggahan file, ekspor database, atau API yang masih menggunakan format tahun 1970-an. Untuk mengonversi CSV ke JSON di JavaScript, Anda membutuhkan dua hal yang diberikan bahasa secara gratis: pemisahan string untuk mem-parse baris dan JSON.stringify() untuk menserialisasi hasilnya. Tidak diperlukan paket npm untuk hal dasar โ€” panduan ini mencakup pipeline lengkap dari utilitas csvToJson() yang dapat digunakan kembali hingga PapaParse dan I/O file Node.js. Untuk konversi cepat tanpa kode, the konverter CSV ke JSON online menanganinya secara instan. Semua contoh ditargetkan untuk Node.js 18+ dan browser modern.

  • โœ“Pisahkan CSV berdasarkan baris baru, ekstrak header dari baris 0, petakan baris yang tersisa ke objek, lalu JSON.stringify(array, null, 2) untuk output yang rapi.
  • โœ“JSON.stringify() menghasilkan string; JSON.parse() mengonversinya kembali ke array JavaScript langsung โ€” ketahui mana yang Anda miliki sebelum mengoperasinya.
  • โœ“Instance Map tidak diserialisasi ke JSON secara otomatis โ€” panggil Object.fromEntries(map) terlebih dahulu.
  • โœ“Untuk CSV dengan kolom yang dikutip, koma di dalam nilai, atau baris baru di sel, gunakan PapaParse atau csv-parse daripada pemisahan manual.
  • โœ“csvtojson (npm) menangani konversi tipe, streaming, dan kasus tepi RFC 4180 dalam satu panggilan.

Apa itu Konversi CSV ke JSON?

Konversi CSV ke JSON mengubah format teks datar yang dibatasi koma menjadi array objek terstruktur di mana setiap baris menjadi objek JavaScript yang dikunci oleh header kolom. Format CSV tidak memiliki tipe data โ€” semuanya adalah string. JSON menambahkan struktur, nesting, dan tipe eksplisit (angka, boolean, null). Konversi ini adalah langkah pertama dalam hampir setiap pipeline data yang dimulai dengan ekspor spreadsheet, dump sistem lama, atau file yang diunggah pengguna. Data yang mendasarinya tetap sama; formatnya berubah dari kolom berbasis posisi menjadi properti bernama.

Before ยท json
After ยท json
name,email,role,active
Budi Santoso,bsantoso@nexuslabs.io,Engineering Lead,true
Sari Dewi,sdewi@nexuslabs.io,Product Manager,true
[
  {
    "name": "Budi Santoso",
    "email": "bsantoso@nexuslabs.io",
    "role": "Engineering Lead",
    "active": "true"
  },
  {
    "name": "Sari Dewi",
    "email": "sdewi@nexuslabs.io",
    "role": "Product Manager",
    "active": "true"
  }
]

csvToJson() โ€” Membangun Fungsi Konversi yang Dapat Digunakan Kembali

Pipeline CSV-ke-JSON lengkap di JavaScript terbagi menjadi tiga langkah: pisahkan string CSV berdasarkan baris baru untuk mendapatkan baris-baris, ekstrak header dari baris pertama dengan split(','), lalu petakan setiap baris yang tersisa ke objek JavaScript biasa di mana key berasal dari header dan nilai berasal dari posisi kolom yang sesuai. Panggilan terakhir ke JSON.stringify() mengonversi array objek tersebut menjadi string JSON. Berikut adalah versi minimal yang berfungsi:

JavaScript โ€” minimal csvToJson
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" }
// ]

Fungsi tersebut menangani hal-hal dasar: baris baru di akhir, baris kosong, spasi di sekitar nilai. Setiap kolom CSV melewati sebagai string. Perhatikan bahwa port adalah "8080" (string), bukan 8080 (angka). Jika Anda membutuhkan tipe yang tepat dalam output JSON, Anda harus melakukan konversi sendiri. Berikut versi yang diperluas dengan deteksi tipe:

JavaScript โ€” csvToJson dengan konversi tipe
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 }
// ]

Flag coerce bersifat opt-in karena deteksi tipe otomatis bisa memberikan efek yang tidak diinginkan โ€” kolom seperti kode pos ("07302") kehilangan angka nol di depannya saat dikonversi ke angka. Nonaktifkan konversi secara default dan aktifkan hanya saat Anda mengontrol skema. Catatan singkat: JSON.stringify() menerima argumen ketiga space untuk indentasi. Berikan 2 untuk dua spasi, 4 untuk empat, atau "\t" untuk tab. Hilangkan sama sekali untuk output satu baris yang ringkas โ€” berguna saat mengirim string JSON sebagai badan permintaan API di mana spasi putih hanya membuang bandwidth.

Catatan:String CSV mentah bukanlah JSON. Memanggil JSON.parse() langsung pada teks CSV akan melempar SyntaxError. Anda harus terlebih dahulu mengonversi CSV ke objek JavaScript dengan fungsi csvToJson() Anda, yang secara internal memanggil JSON.stringify() untuk menghasilkan string JSON aktual.

Menangani Map, Date, dan Objek Kustom dari Data CSV

Tidak setiap konversi CSV berakhir dengan array datar dari objek biasa. Terkadang Anda perlu membangun Map dari pasangan header-nilai, mem-parse string tanggal ke objek Date, atau melampirkan properti yang dihitung sebelum serialisasi. JavaScript memiliki keanehan yang sering membuat orang tersandung: instance Map tidak diserialisasi dengan JSON.stringify(). Anda mendapat objek kosong. Solusinya adalah Object.fromEntries() untuk mengonversi Map kembali ke objek biasa sebelum melakukan stringify.

Alasan Map diserialisasi menjadi {} adalah bahwa JSON.stringify() mengiterasi properti enumerable milik objek sendiri. Map menyimpan entri-entrinya di slot internal, bukan sebagai properti enumerable pada objek itu sendiri, sehingga serializer melihat objek tanpa key. Prototipe Map juga tidak memiliki metode toJSON(), yang merupakan hook yang dipanggil JSON.stringify() pertama kali pada nilai apa pun sebelum memutuskan cara menserialisasinya. Jika nilai memiliki toJSON(), nilai kembalian metode itulah yang diserialisasi โ€” bukan objeknya sendiri. Inilah mengapa objek Date diserialisasi dengan benar: Date.prototype.toJSON mengembalikan string ISO 8601, sehingga JSON.stringify(new Date()) menghasilkan timestamp yang dikutip daripada objek kosong. Memahami hook ini memungkinkan Anda mendefinisikan perilaku yang sama pada kelas Anda sendiri โ€” seperti yang ditunjukkan dalam contoh EmployeeRecord di bawah โ€” untuk mengontrol persis kolom CSV mana yang muncul dalam output JSON akhir.

Mengonversi Map ke JSON

JavaScript โ€” Map ke JSON via Object.fromEntries()
// Bangun Map dari pasangan headerโ†’nilai 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 TIDAK diserialisasi langsung
console.log(JSON.stringify(rowMap))
// "{}"  โ€” objek kosong, data hilang!

// Konversi ke objek biasa terlebih dahulu
const rowObj = Object.fromEntries(rowMap)
console.log(JSON.stringify(rowObj, null, 2))
// {
//   "server": "payments-api",
//   "port": "9090",
//   "region": "ap-south-1"
// }

String Tanggal dan toJSON()

Kolom tanggal CSV datang sebagai string. Jika Anda mem-parse-nya ke objek Date selama pemrosesan, Date tersebut diserialisasi dengan benar karena Date memiliki metode toJSON() bawaan yang mengembalikan string ISO 8601. Anda juga dapat mendefinisikan toJSON() kustom pada kelas Anda sendiri untuk mengontrol kolom CSV mana yang muncul dalam output yang diserialisasi โ€” misalnya, menghilangkan kolom pelacakan internal seperti _rowIndex.

JavaScript โ€” toJSON() untuk serialisasi kustom
class EmployeeRecord {
  constructor(csvRow) {
    this._rowIndex = csvRow._rowIndex  // internal, bukan untuk JSON
    this.employeeId = csvRow.employee_id
    this.name = csvRow.name
    this.hiredAt = new Date(csvRow.hired_date)
    this.salary = Number(csvRow.salary)
  }

  toJSON() {
    // Hanya tampilkan kolom yang ingin ada dalam output JSON
    return {
      employee_id: this.employeeId,
      name: this.name,
      hired_at: this.hiredAt,  // Date.toJSON() โ†’ string ISO secara otomatis
      salary: this.salary,
    }
  }
}

const csvRow = {
  _rowIndex: 42,
  employee_id: 'EMP-2847',
  name: 'Budi Santoso',
  hired_date: '2024-03-15',
  salary: '128000',
}

const record = new EmployeeRecord(csvRow)
console.log(JSON.stringify(record, null, 2))
// {
//   "employee_id": "EMP-2847",
//   "name": "Budi Santoso",
//   "hired_at": "2024-03-15T00:00:00.000Z",
//   "salary": 128000
// }
// Catatan: _rowIndex dikecualikan, salary adalah angka, tanggal dalam format ISO

Reviver untuk Deserialisasi Date

Setelah menulis JSON yang berasal dari CSV ke file atau mengirimkannya melalui jaringan, JSON.parse() mengembalikan objek biasa โ€” objek Date menjadi string lagi. Gunakan fungsi reviver untuk mengonversi string ISO 8601 kembali ke objek Date selama parsing:

JavaScript โ€” reviver untuk merekonstruksi objek Date
const jsonString = '{"employee_id":"EMP-2847","name":"Budi Santoso","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
Peringatan:JSON.stringify() mengembalikan undefined (bukan string) untuk nilai yang mengandung fungsi, Symbol, atau properti undefined. Jika objek yang berasal dari CSV Anda secara tidak sengaja mengambil nilai undefined dari kolom yang hilang, properti tersebut hilang secara diam-diam dari output JSON. Selalu gunakan null sebagai default untuk nilai yang hilang.

Referensi Parameter JSON.stringify()

Tanda tangan fungsinya adalah JSON.stringify(value, replacer?, space?). Argumen replacer dan space keduanya opsional โ€” berikan null untuk replacer saat Anda hanya membutuhkan indentasi.

Parameter
Tipe
Default
Deskripsi
value
any
(wajib)
Nilai JavaScript yang akan diserialisasi โ€” objek, array, string, angka, boolean, atau null
replacer
Function | Array | null
undefined
Filter atau transformasi nilai saat serialisasi. Array membatasi nama properti; fungsi menerima pasangan (key, value)
space
number | string
undefined
Indentasi: angka 0โ€“10 untuk spasi, string (mis. "\t") untuk indent kustom. Hilangkan untuk output satu baris yang ringkas

Parameter JSON.parse():

Parameter
Tipe
Default
Deskripsi
text
string
(wajib)
String JSON yang akan di-parse โ€” harus berupa JSON valid atau SyntaxError akan dilempar
reviver
Function | undefined
undefined
Dipanggil untuk setiap pasangan key-value. Nilai yang dikembalikan menggantikan nilai asli; kembalikan undefined untuk menghapus properti

JSON.parse() โ€” Menggunakan Output JSON

Setelah Anda memiliki string JSON dari csvToJson(), langkah berikutnya biasanya adalah mem-parse-nya kembali ke array JavaScript langsung untuk filtering, mapping, atau mengirimkannya ke API. Perbedaan antara string JSON (typeof === "string") dan objek JavaScript itu penting. Anda tidak dapat memanggil .filter() atau mengakses [0].name pada string โ€” Anda membutuhkan JSON.parse() terlebih dahulu. Perjalanan pulang-pergi ini (stringify lalu parse) juga berfungsi sebagai teknik validasi: jika konversi CSV Anda menghasilkan sesuatu yang bukan JSON valid, parse akan melempar. Argumen reviver opsional memungkinkan Anda mengubah setiap pasangan key-value selama parsing โ€” berguna untuk memulihkan objek Date dari string ISO atau mengganti nama key tanpa proses terpisah.

JavaScript โ€” parse output JSON dan query baris
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`

// Langkah 1: konversi CSV ke string JSON
const jsonString = csvToJson(csv, { coerce: true })

// Langkah 2: parse kembali ke array JavaScript
const endpoints = JSON.parse(jsonString)

// Verifikasi bahwa ini adalah array
console.log(Array.isArray(endpoints))  // true

// Filter endpoint dengan latensi tinggi
const slow = endpoints.filter(ep => ep.avg_latency_ms > 200)
console.log(slow.map(ep => ep.endpoint))
// ["/api/v2/orders", "/api/v2/payments"]

// Destrukturisasi baris pertama
const [first, ...rest] = endpoints
console.log(first.endpoint)  // "/api/v2/orders"
console.log(rest.length)     // 3

Wrapper yang aman untuk JSON.parse() berguna saat memvalidasi output konversi sebelum pemrosesan lebih lanjut. Jika konversi CSV menghasilkan JSON yang cacat karena alasan apa pun (input yang terpotong, kesalahan encoding), ini menangkapnya tanpa crash:

JavaScript โ€” wrapper parse yang aman
function safeParse(jsonString) {
  try {
    return { data: JSON.parse(jsonString), error: null }
  } catch (err) {
    return { data: null, error: err.message }
  }
}

// Output valid
const result = safeParse(csvToJson(csv))
if (result.error) {
  console.error('Konversi CSV menghasilkan JSON tidak valid:', result.error)
} else {
  console.log(`Parsed ${result.data.length} baris`)
}

// Secara tidak sengaja meneruskan CSV mentah ke JSON.parse โ€” ini gagal
const bad = safeParse('name,email\nBudi,bsantoso@nexuslabs.io')
console.log(bad.error)  // "Unexpected token 'a', "name,email"... is not valid JSON"

Reviver untuk Penggantian Nama Key dan Validasi

Fungsi reviver menerima setiap pasangan key-value selama parsing, dari properti paling dalam ke luar. Mengembalikan undefined untuk sebuah key menghapusnya dari hasil sepenuhnya; mengembalikan nilai yang berbeda menggantinya. Reviver berguna untuk mengganti nama header (camelCase ke snake_case), menghapus kolom internal, atau memeriksa apakah kolom yang diperlukan ada. Ia dipanggil dengan nilai root terakhir (key string kosong), di mana Anda melempar jika hasilnya bukan array.

JavaScript โ€” reviver untuk penggantian nama key dan validasi bentuk
const jsonString = csvToJson(`employeeId,firstName,hiredDate
EMP-2847,Budi,2024-03-15
EMP-3012,Sari,2023-11-01`, { coerce: false })

const camelToSnake = str => str.replace(/[A-Z]/g, c => '_' + c.toLowerCase())

const employees = JSON.parse(jsonString, function(key, value) {
  // Nilai root โ€” validasi bentuk
  if (key === '') {
    if (!Array.isArray(value)) throw new Error('Diharapkan array JSON dari CSV')
    return value
  }
  // Ganti nama key header camelCase ke 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: 'Budi', hired_date: '2024-03-15' }

Mengonversi CSV dari File dan Respons API

Dua tempat data CSV sebenarnya berasal dalam produksi: file di disk dan respons HTTP. Kedua skenario memerlukan penanganan error karena input berasal dari luar dan tidak terkontrol.

Baca File CSV, Konversi, Tulis JSON

Node.js 18+ โ€” konversi file
import { readFileSync, writeFileSync } from 'node:fs'

function csvToJsonFromFile(inputPath, outputPath) {
  let csvText
  try {
    csvText = readFileSync(inputPath, 'utf8')
  } catch (err) {
    throw new Error(`Gagal membaca ${inputPath}: ${err.message}`)
  }

  const lines = csvText.trim().split('\n')
  if (lines.length < 2) {
    throw new Error(`${inputPath} tidak memiliki baris data (hanya ${lines.length} baris)`)
  }

  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(`Mengonversi ${rows.length} baris โ†’ ${outputPath}`)
  return rows
}

// Penggunaan
const data = csvToJsonFromFile('inventory.csv', 'inventory.json')
console.log(data[0])
// { sku: "WDG-2847", warehouse: "us-east-1", quantity: "150", ... }

Ambil CSV dari Endpoint API

Node.js 18+ โ€” konversi respons 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 tidak terduga: ${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
}

// Contoh: ambil CSV nilai tukar dari penyedia data
try {
  const rates = await fetchCsvAsJson('https://data.ecb.internal/rates/daily.csv')
  console.log(JSON.stringify(rates.slice(0, 3), null, 2))
  // Kirim sebagai JSON ke layanan hilir
  await fetch('https://api.internal/v2/rates', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ data: rates }),
  })
} catch (err) {
  console.error('Sinkronisasi nilai tukar gagal:', err.message)
}
Catatan:Argumen replacer dalam JSON.stringify() memungkinkan Anda membatasi kolom tertentu dari CSV. Berikan array nama header untuk hanya menyertakan kolom tersebut: JSON.stringify(rows, ['name', 'email', 'department']). Properti yang tidak ada dalam array dikecualikan secara diam-diam dari output.

Konversi CSV ke JSON via Command-Line

Node.js dapat menjalankan skrip inline, dan ada alat CLI khusus yang menangani konversi CSV-ke-JSON tanpa menulis skrip.

bash โ€” Node.js one-liner
# Pipe CSV ke skrip 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) untuk CSV ke JSON
# Miller adalah pisau Swiss Army untuk data terstruktur
# Install: brew install miller (macOS) atau apt install miller (Debian/Ubuntu)
mlr --icsv --ojson cat inventory.csv

# Filter baris selama konversi
mlr --icsv --ojson filter '$quantity > 100' inventory.csv

# Pilih kolom tertentu
mlr --icsv --ojson cut -f sku,warehouse,quantity inventory.csv
bash โ€” csvtojson CLI
# Install secara global
npm install -g csvtojson

# Konversi file
csvtojson servers.csv > servers.json

# Pipe dari stdin
cat exports/q1-metrics.csv | csvtojson > q1-metrics.json

Untuk file besar, Miller biasanya merupakan pilihan yang lebih baik daripada csvtojson. Miller diimplementasikan dalam C dan memproses CSV sebagai stream tanpa memuat seluruh file ke dalam memori, yang berarti ia menangani ekspor multi-gigabyte dengan penggunaan memori yang konstan. Ia juga mendukung operasi tingkat kolom di tempat โ€” mengganti nama kolom, mengkonversi tipe nilai, memfilter baris โ€” sebelum data menjadi JSON, sehingga Anda menghindari pipeline parse-lalu-transform dua langkah. csvtojson, di sisi lain, berjalan di Node.js dan lebih mudah digunakan saat toolchain Anda yang lain adalah JavaScript: Anda dapat mem-pipe outputnya langsung ke stream Node, mengimpornya sebagai library, atau menggunakan API colParser-nyauntuk konversi tipe per kolom dalam kode. Gunakan Miller untuk throughput mentah dan pipeline shell; gunakan csvtojson saat Anda membutuhkan integrasi erat dengan aplikasi Node.js.

Catatan:jq tidak mem-parse CSV secara native. Jika Anda membutuhkan jq dalam pipeline, konversi ke JSON terlebih dahulu dengan csvtojson atau mlr, lalu pipe output JSON ke jq untuk filtering dan transformasi.

Alternatif Berkinerja Tinggi โ€” PapaParse

Pendekatan manual split(',') gagal pada file CSV dunia nyata. Kolom yang dikutip yang mengandung koma, baris baru yang tertanam, tanda kutip ganda yang di-escape โ€” semua ini merusak pemisah naif. PapaParse adalah library yang saya gunakan ketika CSV berasal dari sumber yang tidak diketahui. Ia menangani setiap kasus tepi RFC 4180, mendeteksi delimiter secara otomatis, dan bekerja di Node.js dan browser.

bash โ€” install PapaParse
npm install papaparse
JavaScript โ€” PapaParse dengan konversi tipe
import Papa from 'papaparse'

const csv = `product,description,price,in_stock
"Widget, Large","A premium widget with ""extra"" features",29.99,true
Bolt Assembly,Standard M8 bolt kit,4.50,true
"Gasket Set","Includes gasket, seal, and O-ring",12.75,false`

const { data, errors, meta } = Papa.parse(csv, {
  header: true,
  dynamicTyping: true,     // otomatis mengonversi angka dan boolean
  skipEmptyLines: true,
  transformHeader: h => h.trim().toLowerCase().replace(/\s+/g, '_'),
})

if (errors.length > 0) {
  console.error('Error parsing:', errors)
}

console.log(JSON.stringify(data, null, 2))
// [
//   {
//     "product": "Widget, Large",
//     "description": "A premium widget with \"extra\" features",
//     "price": 29.99,
//     "in_stock": true
//   },
//   ...
// ]
console.log(`Parsed ${data.length} baris, delimiter: "${meta.delimiter}"`)

Opsi dynamicTyping PapaParse melakukan konversi tipe secara otomatis โ€” angka menjadi angka, "true"/"false" menjadi boolean. Callback transformHeader menormalkan nama kolom ke snake_case, yang menghemat Anda dari berurusan dengan header yang tidak konsisten dari ekspor CSV yang berbeda. Untuk konversi cepat tanpa menulis kode parsing apa pun, the konverter CSV ke JSON menangani semua ini di browser.

Output Terminal dengan Syntax Highlighting

Membuang array JSON besar ke terminal membuat mata cepat lelah. Menambahkan syntax highlighting ke output membuatnya mudah dibaca selama debugging dan pengembangan. Paket cli-highlight mewarnai output JSON di terminal Node.js.

bash โ€” install cli-highlight
npm install cli-highlight
JavaScript โ€” output JSON berwarna di terminal
import { highlight } from 'cli-highlight'

// Setelah mengonversi CSV ke array JSON
const jsonOutput = JSON.stringify(rows, null, 2)

// Cetak dengan syntax highlighting
console.log(highlight(jsonOutput, { language: 'json' }))
// Key, string, angka, dan boolean masing-masing mendapat warna berbeda

Output berwarna sangat berguna saat Anda memeriksa hasil konversi besar secara interaktif. Key JSON, nilai string, angka, dan boolean masing-masing mendapat warna ANSI berbeda, yang memudahkan untuk menemukan kolom yang tipenya salah โ€” misalnya, nomor port yang seharusnya 8080 tetapi disorot sebagai string karena konversi dinonaktifkan. Ini sangat berguna saat men-debug file CSV yang diekspor dari alat spreadsheet di mana tipe kolom tidak konsisten di seluruh baris. Tanpa warna, memindai 50 baris JSON untuk satu kolom yang salah tipe berarti membaca setiap nilai satu per satu. Dengan warna, angka berwarna string langsung terlihat.

Peringatan:Syntax highlighting menambahkan kode escape ANSI ke output. Jangan gunakan saat menulis JSON ke file, mem-pipe ke program lain, atau mengirim sebagai badan respons API โ€” kode escape akan merusak JSON. Gunakan highlighting hanya untuk tampilan terminal.

Bekerja dengan File CSV Besar

Memuat file CSV 500 MB ke dalam string dengan readFileSync() akan menghabiskan memori dan berpotensi mematikan proses Anda. Untuk file besar, stream CSV baris per baris dan emit objek JSON saat datang. Paket csv-parse (bagian dari ekosistem csv di npm) menyediakan parser streaming yang bekerja dengan stream Node.js.

Streaming CSV ke NDJSON dengan csv-parse

NDJSON (Newline-Delimited JSON) adalah format di mana setiap baris file output adalah objek JSON yang mandiri. Tidak seperti array JSON besar tunggal โ€” yang memerlukan seluruh file ada di memori sebelum Anda dapat mulai membacanya โ€” file NDJSON dapat diproses baris per baris. Ini membuat NDJSON ideal untuk dataset besar yang akan dikonsumsi oleh prosesor log, pipeline stream, atau database dengan API bulk-import. Paket csv-parse memancarkan satu objek JavaScript per baris CSV dalam mode objek, sehingga Anda dapat mem-pipe-nya langsung ke transform stream yang menambahkan \n setelah setiap JSON.stringify(row).

Node.js 18+ โ€” streaming CSV ke NDJSON
import { createReadStream, createWriteStream } from 'node:fs'
import { parse } from 'csv-parse'
import { Transform } from 'node:stream'
import { pipeline } from 'node:stream/promises'

// Transformasi setiap objek baris CSV ke baris 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,       // gunakan baris pertama sebagai header
    skip_empty_lines: true,
    trim: true,
    cast: true,          // otomatis konversi angka dan boolean
  }),
  toNdjson,
  createWriteStream('telemetry-2026-03.ndjson')
)

console.log('Konversi streaming selesai')
// Setiap baris dalam file output adalah satu objek 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}
// ...

PapaParse Streaming untuk Browser dan Node.js

Mode streaming PapaParse menggunakan callback step yang dipicu sekali per baris daripada mengumpulkan semua baris di memori. Anda meneruskan ReadStream Node.js (di Node.js) atau objek File (di browser) dan PapaParse menangani chunking secara internal. Tidak ada pipeline stream yang perlu dikonfigurasi โ€” cukup sebuah callback. Gunakan saat Anda membutuhkan kepatuhan RFC 4180 tanpa menarik csv-parse.

Node.js โ€” PapaParse streaming file besar
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) {
    // Proses satu baris sekaligus โ€” memori konstan
    rowCount++
    if (result.data.quantity === 0) {
      errors.push(`Baris ${rowCount}: ${result.data.sku} kehabisan stok`)
    }
  },
  complete() {
    console.log(`Memproses ${rowCount} baris`)
    if (errors.length > 0) {
      console.log(`Masalah ditemukan: ${errors.length}`)
      errors.forEach(e => console.log(`  ${e}`))
    }
  },
  error(err) {
    console.error('Parsing gagal:', err.message)
  },
})
Catatan:Beralih ke streaming ketika file CSV Anda melebihi 50 MB atau ketika Anda memproses input yang tidak terbatas (feed WebSocket, server-sent events, stdin yang di-pipe). Format NDJSON (satu objek JSON per baris) sering kali merupakan format output yang lebih baik daripada array JSON besar untuk dataset besar โ€” ia dapat diproses baris per baris tanpa memuat seluruh file ke dalam memori.

Kesalahan Umum

โŒ Memanggil JSON.parse() langsung pada string CSV

Masalah: CSV bukan JSON. Meneruskan string CSV mentah ke JSON.parse() melempar SyntaxError karena koma dan baris baru bukan sintaks JSON yang valid.

Solusi: Parse CSV ke objek JavaScript terlebih dahulu menggunakan split() atau library, lalu gunakan JSON.stringify() untuk menghasilkan JSON. Hanya panggil JSON.parse() pada string yang sudah berupa JSON valid.

Before ยท JavaScript
After ยท JavaScript
const csv = 'name,email\nBudi Santoso,bsantoso@nexuslabs.io'
const data = JSON.parse(csv)
// SyntaxError: Unexpected token 'a'
const csv = 'name,email\nBudi Santoso,bsantoso@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)  // string JSON valid
โŒ Menggunakan toString() daripada JSON.stringify()

Masalah: Memanggil toString() pada objek JavaScript mengembalikan string yang tidak berguna '[object Object]' daripada data aktual. Ini diam-diam merusak output CSV-ke-JSON Anda.

Solusi: Selalu gunakan JSON.stringify() untuk mengonversi objek JavaScript ke string JSON. toString() ada untuk konversi primitif-ke-string, bukan untuk serialisasi.

Before ยท JavaScript
After ยท JavaScript
const row = { server: 'api-gateway', port: 8080 }
const output = row.toString()
// "[object Object]"  โ€” data hilang
const row = { server: 'api-gateway', port: 8080 }
const output = JSON.stringify(row, null, 2)
// '{"server":"api-gateway","port":8080}'
โŒ Memisahkan dengan koma tanpa menangani kolom yang dikutip

Masalah: Pemisahan naif split(",") rusak ketika nilai CSV mengandung koma di dalam kolom yang dikutip: "Widget, Large" menjadi dua nilai terpisah alih-alih satu.

Solusi: Gunakan PapaParse atau csv-parse untuk data CSV apa pun yang tidak sepenuhnya Anda kontrol. Jika Anda harus mem-parse secara manual, implementasikan parser state-machine yang melacak apakah posisi saat ini berada di dalam kolom yang dikutip.

Before ยท JavaScript
After ยท JavaScript
const line = '"Widget, Large","Premium quality",29.99'
const values = line.split(',')
// ["\"Widget", " Large\"", "\"Premium quality\"", "29.99"]
// 4 nilai alih-alih 3 โ€” kolom pertama dipisah secara tidak benar
import Papa from 'papaparse'
const { data } = Papa.parse('"Widget, Large","Premium quality",29.99')
// data[0] = ["Widget, Large", "Premium quality", "29.99"]
// 3 nilai, diparsing dengan benar
โŒ Melupakan bahwa semua nilai CSV adalah string

Masalah: Tanpa konversi tipe, port: "8080" tetap sebagai string dalam JSON alih-alih angka. Sistem hilir yang mengharapkan tipe numerik menolak atau menangani data secara salah.

Solusi: Terapkan konversi tipe eksplisit selama langkah pemetaan, atau gunakan PapaParse dengan dynamicTyping: true. Selalu sengaja tentang kolom mana yang harus numerik.

Before ยท JavaScript
After ยท JavaScript
const row = { port: '8443', debug: 'true', workers: '4' }
JSON.stringify(row)
// {"port":"8443","debug":"true","workers":"4"}  โ€” semua string
const row = {
  port: Number('8443'),           // 8443
  debug: 'true' === 'true',      // true
  workers: Number('4'),           // 4
}
JSON.stringify(row)
// {"port":8443,"debug":true,"workers":4}  โ€” tipe yang benar

Parsing Manual vs Library โ€” Perbandingan Singkat

Metode
Output Rapi
JSON Valid
Tipe Kustom
Streaming
Perlu Install
JSON.stringify()
โœ“ (dengan space)
โœ“
โœ“ via toJSON()/replacer
โœ—
Tidak (bawaan)
JSON.parse()
T/A (parsing)
โœ“ (memvalidasi)
โœ“ via reviver
โœ—
Tidak (bawaan)
csv-parse (Node.js)
โœ— (mengembalikan objek)
โœ— (bukan JSON)
โœ—
โœ“
npm install
PapaParse
โœ— (mengembalikan objek)
โœ— (bukan JSON)
โœ—
โœ“
npm install
csvtojson
โœ“
โœ“
โœ“ via colParser
โœ“
npm install
jq (CLI)
โœ“
โœ“
T/A
โœ“
Install sistem
Miller (CLI)
โœ“
โœ“
T/A
โœ“
Install sistem

Untuk skrip cepat di mana Anda mengontrol format CSV dan tahu tidak ada kolom yang dikutip, pendekatan bawaan split() + JSON.stringify() berfungsi dan memerlukan nol dependensi. Untuk sistem produksi yang memproses file CSV yang diunggah pengguna, gunakan PapaParse di browser atau csv-parse di Node.js โ€” keduanya menangani RFC 4180 dengan benar dan mendukung streaming. Paket csvtojson adalah satu-satunya yang menghasilkan JSON langsung, menangani parsing dan serialisasi dalam satu panggilan. Saat Anda membutuhkan jalur tercepat dari tempel-ke-hasil, the konverter CSV ke JSON menangani semuanya di browser tanpa setup apa pun.

Pertanyaan yang Sering Diajukan

Bagaimana cara mengonversi CSV ke JSON di JavaScript tanpa library?

Pisahkan string CSV berdasarkan baris baru untuk mendapatkan baris-baris data, ekstrak header dari baris pertama dengan split(","), lalu petakan baris yang tersisa ke objek yang dikunci oleh header tersebut. Selesaikan dengan JSON.stringify(array, null, 2) untuk menghasilkan string JSON yang terformat. Pendekatan ini cocok untuk file CSV sederhana di mana Anda mengontrol formatnya dan tahu tidak ada kolom yang dikutip atau koma di dalam nilai. Untuk data dari ekspor spreadsheet atau sistem pihak ketiga, kolom yang dikutip dan nilai multi-baris akan merusak pemisah naif โ€” gunakan PapaParse atau csv-parse dalam kasus tersebut. Untuk file yang sangat kecil yang diproses di browser, pendekatan tanpa dependensi ini sangat ideal.

JavaScript
const csv = `name,email,department
Budi Santoso,bsantoso@nexuslabs.io,Engineering
Sari Dewi,sdewi@nexuslabs.io,Product`

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))
// [
//   { "name": "Budi Santoso", "email": "bsantoso@nexuslabs.io", "department": "Engineering" },
//   { "name": "Sari Dewi", "email": "sdewi@nexuslabs.io", "department": "Product" }
// ]

Apa perbedaan antara JSON.stringify() dan toString() untuk objek?

toString() pada objek biasa mengembalikan string yang tidak berguna "[object Object]" โ€” tidak memberikan informasi apapun tentang data aktualnya. JSON.stringify() menghasilkan string JSON yang valid dengan semua key dan value yang diserialisasi dengan benar, termasuk objek dan array yang bersarang. Selalu gunakan JSON.stringify() ketika Anda perlu mengonversi objek JavaScript (seperti baris yang berasal dari CSV) ke string JSON. Untuk membalik operasi โ€” merekonstruksi objek JavaScript langsung dari string JSON โ€” gunakan JSON.parse(), yang merupakan kebalikan tepat dari JSON.stringify(). Kedua fungsi ini membentuk perjalanan pulang-pergi yang lengkap: stringify untuk menyimpan atau mengirim data, parse untuk menggunakannya.

JavaScript
const row = { name: 'Budi Santoso', role: 'Engineer' }

console.log(row.toString())       // "[object Object]"
console.log(JSON.stringify(row))   // '{"name":"Budi Santoso","role":"Engineer"}'

Bagaimana cara menangani kolom CSV yang mengandung koma atau tanda kutip?

RFC 4180 menetapkan bahwa kolom yang mengandung koma, baris baru, atau tanda kutip ganda harus dibungkus dalam tanda kutip ganda, dengan tanda kutip di dalamnya di-escape dengan cara menggandakannya ("" di dalam kolom yang dikutip mewakili satu tanda kutip literal). Pemisahan manual dengan split(",") tidak berfungsi pada file seperti ini โ€” batas kolom bukan lagi koma biasa. Gunakan PapaParse atau csv-parse untuk data produksi, atau tulis parser state-machine yang melacak apakah Anda berada di dalam kolom yang dikutip. Menulis state machine yang benar dari awal ternyata cukup rumit: Anda harus menangani tanda kutip di awal kolom, tanda kutip di-escape di tengah kolom, baris baru di dalam kolom yang dikutip, dan konvensi akhir baris yang berbeda (CRLF vs LF). Untuk data CSV apa pun di luar data mainan, gunakan library yang telah teruji.

JavaScript
// PapaParse menangani RFC 4180 dengan benar
import Papa from 'papaparse'

const csv = `product,description,price
"Widget, Large","A big ""widget""",29.99
Bolt,Standard bolt,1.50`

const { data } = Papa.parse(csv, { header: true })
console.log(JSON.stringify(data, null, 2))
// kolom description berisi dengan benar: A big "widget"

Bisakah saya mengonversi CSV ke JSON langsung di browser?

Ya. Baik JSON.stringify() maupun JSON.parse() sudah tersedia di setiap mesin browser. Untuk langkah parsing CSV, Anda dapat memisahkan berdasarkan baris baru dan koma untuk file sederhana, atau menyertakan PapaParse melalui CDN (tidak memiliki dependensi Node.js). Seluruh konversi terjadi di sisi klien tanpa perjalanan bolak-balik ke server, yang berguna untuk privasi file โ€” data CSV mentah tidak pernah meninggalkan mesin pengguna. Ketika pengguna mengunggah file CSV melalui elemen <input type="file">, metode file.text() dari File API mengembalikan Promise yang diselesaikan ke konten file sebagai string, yang kemudian dapat Anda teruskan ke fungsi konversi. Ini membuat konversi CSV-ke-JSON sepenuhnya di browser menjadi praktis untuk dasbor, alat pengembang, dan aplikasi apa pun yang perlu memproses data yang diunggah tanpa backend.

JavaScript
// Browser: pengguna mengunggah 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))
})

Bagaimana cara mem-parse nilai numerik dan boolean dari CSV alih-alih menyimpan semuanya sebagai string?

CSV tidak memiliki sistem tipe โ€” setiap kolom adalah string. Anda harus memaksa konversi nilai selama langkah pemetaan. Periksa pola numerik dengan Number() atau parseFloat(), konversi "true"/"false" ke boolean, dan tangani string kosong sebagai null. Berhati-hatilah dengan kolom yang terlihat seperti angka tetapi harus tetap sebagai string: kode pos seperti "07302" kehilangan angka nol di depannya saat dipaksa dengan Number(), dan nomor telepon atau kode produk dengan karakter numerik juga sama rapuhnya. Library csvtojson melakukan konversi tipe otomatis melalui opsi colParser-nya, yang memungkinkan Anda menentukan fungsi konversi per kolom dan mengganti deteksi otomatis untuk kolom yang bermasalah. Opsi dynamicTyping PapaParse menerapkan konversi yang sama secara global di semua kolom.

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
}

// Terapkan selama pemetaan CSV ke objek
const row = { port: coerceValue('8443'), debug: coerceValue('true'), host: coerceValue('api.internal') }
// { port: 8443, debug: true, host: "api.internal" }

Bagaimana cara menulis output CSV-ke-JSON ke file di Node.js?

Gunakan fs.writeFileSync() dengan output JSON.stringify(). Argumen ketiga untuk JSON.stringify mengontrol indentasi โ€” berikan 2 untuk indentasi dua spasi atau "\t" untuk tab. Untuk membaca file kembali, gunakan JSON.parse(fs.readFileSync(path, "utf8")), yang merekonstruksi array JavaScript langsung dari objek. Jika Anda menulis file dalam konteks async (di dalam fungsi async atau di level atas modul ES), gunakan fs.promises.writeFile() untuk menghindari pemblokiran event loop selama penulisan file selesai. Untuk output JSON yang besar lebih dari beberapa megabyte, pertimbangkan untuk mem-pipe stream JSON ke WriteStream daripada membangun seluruh string di memori sebelum menulis.

JavaScript
import { writeFileSync, readFileSync } from 'node:fs'

// Tulis
const jsonOutput = JSON.stringify(rows, null, 2)
writeFileSync('karyawan.json', jsonOutput, 'utf8')

// Baca kembali
const parsed = JSON.parse(readFileSync('karyawan.json', 'utf8'))
console.log(Array.isArray(parsed))  // true
console.log(parsed[0].name)         // "Budi Santoso"

Alat Terkait

Tersedia juga dalam: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 LaurentPeninjau teknis

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.