CSV to JSON JavaScript — Converter + Code Examples
از تبدیل CSV به JSON آنلاین رایگان مستقیم در مرورگرتان استفاده کنید — نیازی به نصب نیست.
امتحان کردن تبدیل CSV به JSON آنلاین ←بیشتر دادههای CSV که با آنها مواجه میشوم بهصورت یک رشته ساده از آپلود فایل، صادرات پایگاه داده، یا یک API که هنوز با فرمت دهه شصت کار میکند میرسند. برای تبدیل CSV به JSON در JavaScript، به دو چیزی نیاز دارید که زبان بهرایگان به شما میدهد: تقسیم رشته برای تجزیه ردیفها و JSON.stringify() برای تبدیل نتیجه به رشته. برای کارهای پایه هیچ پکیج npm لازم نیست — این راهنما کل pipeline را از یک تابع قابل استفاده مجدد csvToJson() تا PapaParse و ورودی/خروجی فایل در Node.js پوشش میدهد. برای تبدیل سریع بدون کد، مبدل آنلاین CSV به JSON فوری انجامش میدهد. همه مثالها برای Node.js 18+ و مرورگرهای مدرن هستند.
- ✓CSV را با newline تقسیم کنید، سرستونها را از ردیف ۰ استخراج کنید، ردیفهای باقیمانده را به آبجکت نگاشت کنید، سپس JSON.stringify(array, null, 2) برای خروجی زیبا.
- ✓JSON.stringify() یک رشته تولید میکند؛ JSON.parse() آن را به آرایه زنده JavaScript تبدیل میکند — قبل از عملیات روی آن بدانید کدامیک را دارید.
- ✓نمونههای Map بهطور خودکار به JSON تبدیل نمیشوند — ابتدا Object.fromEntries(map) را فراخوانی کنید.
- ✓برای CSV با فیلدهای نقلقولدار، کاما داخل مقادیر، یا newline در سلولها، به جای تقسیم دستی از PapaParse یا csv-parse استفاده کنید.
- ✓csvtojson (npm) تبدیل نوع، استریمینگ، و موارد لبهای RFC 4180 را در یک فراخوانی مدیریت میکند.
تبدیل CSV به JSON چیست؟
تبدیل CSV به JSON یک فرمت متن مسطح با کاما بهعنوان جداکننده را به آرایهای ساختارمند از آبجکتها تبدیل میکند که هر ردیف به یک آبجکت JavaScript با کلیدهای سرستون تبدیل میشود. فرمت CSV سیستم نوع داده ندارد — همه چیز رشته است. JSON ساختار، تودرتوشدن، و نوعهای صریح (اعداد، boolean، null) اضافه میکند. این تبدیل اولین قدم در تقریباً هر pipeline دادهای است که با صادرات صفحهگسترده، dump سیستم قدیمی، یا فایل آپلودشده توسط کاربر شروع میشود. دادههای زیرین یکسان میمانند؛ فرمت از ستونهای مبتنی بر موقعیت به خصوصیات نامگذاریشده تغییر میکند.
[
{
"name": "علی رضایی",
"email": "ali@nexuslabs.io",
"role": "Engineering Lead",
"active": "true"
},
{
"name": "زهرا محمدی",
"email": "zahra@nexuslabs.io",
"role": "Product Manager",
"active": "true"
}
]name,email,role,active علی رضایی,ali@nexuslabs.io,Engineering Lead,true زهرا محمدی,zahra@nexuslabs.io,Product Manager,true
csvToJson() — ساخت یک تابع تبدیل قابل استفاده مجدد
کل pipeline CSV-به-JSON در JavaScript به سه مرحله تقسیم میشود: رشته CSV را با newline تقسیم کنید تا ردیفها به دست آیند، سرستونها را از اولین ردیف با split(',') استخراج کنید، سپس هر ردیف باقیمانده را به یک آبجکت JavaScript ساده نگاشت کنید که کلیدها از سرستونها و مقادیر از موقعیتهای ستون متناظر میآیند. آخرین فراخوانی به JSON.stringify() آن آرایه از آبجکتها را به رشته JSON تبدیل میکند. اینجا یک نسخه حداقلی کاربردی است:
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" }
// ]آن تابع کارهای پایه را انجام میدهد: newlineهای انتهایی، خطوط خالی، فاصله اطراف مقادیر. هر فیلد CSV بهصورت رشته میآید. توجه کنید که port برابر "8080" است (یک رشته)، نه 8080 (یک عدد). اگر به نوعهای مناسب در خروجی JSON نیاز دارید، باید آنها را خودتان تبدیل کنید. اینجا یک نسخه توسعهیافته با تشخیص نوع است:
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 }
// ]پرچم coerce بهصورت اختیاری است زیرا تشخیص نوع خودکار میتواند نتیجه معکوس داشته باشد — فیلدی مثل کدپستی ("07302") صفر پیشاهنگ خود را با تبدیل به عدد از دست میدهد. تبدیل را بهصورت پیشفرض غیرفعال نگه دارید و فقط وقتی schema را کنترل میکنید فعال کنید. نکته مختصر: JSON.stringify() یک آرگومان سوم space برای تورفتگی قبول میکند. 2 برای دو فاصله، 4 برای چهار، یا "\t" برای tab بگذارید. برای خروجی فشرده تکخطی آن را کاملاً حذف کنید — مفید هنگامی که رشته JSON را بهعنوان بدنه درخواست API ارسال میکنید که فضای خالی فقط پهنای باند هدر میدهد.
JSON.parse() مستقیماً روی متن CSV یک SyntaxError پرتاب میکند. ابتدا باید CSV را به آبجکتهای JavaScript با تابع csvToJson() خود تبدیل کنید، که داخلاً JSON.stringify() را برای تولید رشته JSON واقعی فراخوانی میکند.مدیریت Map، تاریخ، و آبجکتهای سفارشی از دادههای CSV
نه هر تبدیل CSV با یک آرایه مسطح از آبجکتهای ساده تمام میشود. گاهی نیاز دارید از جفتهای سرستون-مقدار یک Map بسازید، رشتههای تاریخ را به آبجکت Date تبدیل کنید، یا خصوصیات محاسبهشده قبل از تبدیل اضافه کنید. JavaScript یک ویژگی دارد که مردم را گیج میکند: نمونههای Map با JSON.stringify() تبدیل نمیشوند. یک آبجکت خالی میگیرید. راهحل Object.fromEntries() برای تبدیل Map به آبجکت ساده قبل از تبدیل به رشته است.
دلیل اینکه Map به {} تبدیل میشود این است که JSON.stringify() روی خصوصیات قابل شمارش خودِ یک آبجکت تکرار میکند. یک Map ورودیهای خود را در یک اسلات داخلی ذخیره میکند، نه بهعنوان خصوصیات قابل شمارش روی خود آبجکت، بنابراین تبدیلکننده آبجکتی بدون کلید میبیند. پروتوتایپ Map همچنین متد toJSON() ندارد، که hookای است که JSON.stringify() ابتدا روی هر مقداری قبل از تصمیمگیری درباره نحوه تبدیل فراخوانی میکند. اگر یک مقدار toJSON() داشته باشد، مقدار بازگشتی متد چیزی است که تبدیل میشود — نه خود آبجکت. به همین دلیل آبجکتهای Date بهدرستی تبدیل میشوند: Date.prototype.toJSON یک رشته ISO 8601 برمیگرداند، بنابراین JSON.stringify(new Date()) یک timestamp نقلقولدار تولید میکند نه یک آبجکت خالی. درک این hook به شما اجازه میدهد همان رفتار را روی کلاسهای خود تعریف کنید — همانطور که در مثال EmployeeRecord زیر نشان داده شده — تا دقیقاً کنترل کنید کدام فیلدهای مشتقشده از CSV در خروجی JSON نهایی ظاهر میشوند.
تبدیل Map به JSON
// Build a Map from CSV header→value pairs
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 does NOT serialize directly
console.log(JSON.stringify(rowMap))
// "{}" — empty object, data lost!
// Convert to plain object first
const rowObj = Object.fromEntries(rowMap)
console.log(JSON.stringify(rowObj, null, 2))
// {
// "server": "payments-api",
// "port": "9090",
// "region": "ap-south-1"
// }رشتههای تاریخ و toJSON()
فیلدهای تاریخ در CSV بهصورت رشته میرسند. اگر آنها را در طول پردازش به آبجکت Date تبدیل کنید، آن Dateها بهدرستی تبدیل میشوند زیرا Date یک متد toJSON() داخلی دارد که یک رشته ISO 8601 برمیگرداند. همچنین میتوانید toJSON() سفارشی روی کلاسهای خود تعریف کنید تا کنترل کنید کدام ستونهای CSV در خروجی تبدیلشده ظاهر میشوند — برای مثال، حذف فیلدهای ردیابی داخلی مثل _rowIndex.
class EmployeeRecord {
constructor(csvRow) {
this._rowIndex = csvRow._rowIndex // internal, not for JSON
this.employeeId = csvRow.employee_id
this.name = csvRow.name
this.hiredAt = new Date(csvRow.hired_date)
this.salary = Number(csvRow.salary)
}
toJSON() {
// Only expose fields we want in the JSON output
return {
employee_id: this.employeeId,
name: this.name,
hired_at: this.hiredAt, // Date.toJSON() → ISO string automatically
salary: this.salary,
}
}
}
const csvRow = {
_rowIndex: 42,
employee_id: 'EMP-2847',
name: 'علی رضایی',
hired_date: '2024-03-15',
salary: '128000',
}
const record = new EmployeeRecord(csvRow)
console.log(JSON.stringify(record, null, 2))
// {
// "employee_id": "EMP-2847",
// "name": "علی رضایی",
// "hired_at": "2024-03-15T00:00:00.000Z",
// "salary": 128000
// }
// Note: _rowIndex is excluded, salary is a number, date is ISO formatReviver برای deserialize کردن تاریخ
بعد از نوشتن JSON مشتقشده از CSV در فایل یا ارسال آن از طریق شبکه، JSON.parse() آبجکتهای ساده را برمیگرداند — آبجکتهای Date دوباره به رشته تبدیل میشوند. از یک تابع reviver استفاده کنید تا رشتههای ISO 8601 را در طول تجزیه به آبجکت Date تبدیل کنید:
const jsonString = '{"employee_id":"EMP-2847","name":"علی رضایی","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() برای مقادیری که حاوی توابع، Symbol، یا خصوصیات undefined هستند، مقدار undefined (نه یک رشته) برمیگرداند. اگر آبجکتهای مشتقشده از CSV شما بهطور تصادفی یک مقدار undefined از یک ستون گمشده دریافت کنند، آن خصوصیت بیسروصدا از خروجی JSON ناپدید میشود. همیشه مقادیر گمشده را بهصورت null پیشفرض کنید.مرجع پارامترهای JSON.stringify()
امضای تابع JSON.stringify(value, replacer?, space?) است. آرگومانهای replacer و space هر دو اختیاری هستند — وقتی فقط به تورفتگی نیاز دارید null برای replacer بگذارید.
پارامترهای JSON.parse():
JSON.parse() — مصرف خروجی JSON
وقتی یک رشته JSON از csvToJson() دارید، قدم بعدی معمولاً تجزیه آن به یک آرایه زنده JavaScript برای فیلتر کردن، نگاشت، یا ارسال به API است. تفاوت بین رشته JSON (typeof === "string") و آبجکت JavaScript اهمیت دارد. نمیتوانید .filter() فراخوانی کنید یا به [0].name روی یک رشته دسترسی داشته باشید — ابتدا به JSON.parse() نیاز دارید. این دور کامل (stringify سپس parse) همچنین بهعنوان یک تکنیک اعتبارسنجی کار میکند: اگر تبدیل CSV شما چیزی تولید کرد که JSON معتبر نیست، parse پرتاب میکند. آرگومان اختیاری reviver به شما اجازه میدهد هر جفت کلید-مقدار را در طول تجزیه تبدیل کنید — مفید برای بازگرداندن آبجکتهای Date از رشتههای ISO یا تغییر نام کلیدها بدون یک پاس جداگانه.
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`
// Step 1: convert CSV to JSON string
const jsonString = csvToJson(csv, { coerce: true })
// Step 2: parse back to JavaScript array
const endpoints = JSON.parse(jsonString)
// Verify it is an array
console.log(Array.isArray(endpoints)) // true
// Filter high-latency endpoints
const slow = endpoints.filter(ep => ep.avg_latency_ms > 200)
console.log(slow.map(ep => ep.endpoint))
// ["/api/v2/orders", "/api/v2/payments"]
// Destructure the first row
const [first, ...rest] = endpoints
console.log(first.endpoint) // "/api/v2/orders"
console.log(rest.length) // 3یک wrapper امن برای JSON.parse() هنگام اعتبارسنجی خروجی تبدیل قبل از پردازش downstream مفید است. اگر تبدیل CSV به هر دلیلی JSON ناقص تولید کند (ورودی قطعشده، خطاهای encoding)، این آن را بدون crash کردن میگیرد:
function safeParse(jsonString) {
try {
return { data: JSON.parse(jsonString), error: null }
} catch (err) {
return { data: null, error: err.message }
}
}
// Valid output
const result = safeParse(csvToJson(csv))
if (result.error) {
console.error('CSV conversion produced invalid JSON:', result.error)
} else {
console.log(`Parsed ${result.data.length} rows`)
}
// Accidentally passing raw CSV to JSON.parse — this fails
const bad = safeParse('name,email\nعلی,ali@nexuslabs.io')
console.log(bad.error) // "Unexpected token 'a', "name,email"... is not valid JSON"Reviver برای تغییر نام کلید و اعتبارسنجی
تابع reviver هر جفت کلید-مقدار را در طول تجزیه، از داخلیترین خصوصیات به خارج دریافت میکند. بازگرداندن undefined برای یک کلید آن را کاملاً از نتیجه حذف میکند؛ بازگرداندن یک مقدار متفاوت آن را جایگزین میکند. reviver برای تغییر نام سرستونها (camelCase به snake_case)، حذف فیلدهای داخلی، یا بررسی وجود ستونهای الزامی مفید است. با مقدار ریشه در آخر فراخوانی میشود (کلید رشته خالی)، که جایی است که اگر نتیجه آرایه نیست پرتاب میکنید.
const jsonString = csvToJson(`employeeId,firstName,hiredDate
EMP-2847,علی,2024-03-15
EMP-3012,زهرا,2023-11-01`, { coerce: false })
const camelToSnake = str => str.replace(/[A-Z]/g, c => '_' + c.toLowerCase())
const employees = JSON.parse(jsonString, function(key, value) {
// Root value — validate shape
if (key === '') {
if (!Array.isArray(value)) throw new Error('Expected JSON array from CSV')
return value
}
// Rename camelCase header keys to 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: 'علی', hired_date: '2024-03-15' }تبدیل CSV از فایل و پاسخ API
دو جایی که دادههای CSV در محیط تولید واقعاً از آنها میآیند: فایلهای روی دیسک و پاسخهای HTTP. هر دو سناریو به مدیریت خطا نیاز دارند زیرا ورودی خارجی و کنترلنشده است.
خواندن فایل CSV، تبدیل، نوشتن JSON
import { readFileSync, writeFileSync } from 'node:fs'
function csvToJsonFromFile(inputPath, outputPath) {
let csvText
try {
csvText = readFileSync(inputPath, 'utf8')
} catch (err) {
throw new Error(`Failed to read ${inputPath}: ${err.message}`)
}
const lines = csvText.trim().split('\n')
if (lines.length < 2) {
throw new Error(`${inputPath} has no data rows (only ${lines.length} line)`)
}
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(`Converted ${rows.length} rows → ${outputPath}`)
return rows
}
// Usage
const data = csvToJsonFromFile('inventory.csv', 'inventory.json')
console.log(data[0])
// { sku: "WDG-2847", warehouse: "us-east-1", quantity: "150", ... }دریافت CSV از یک 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(`Unexpected content-type: ${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
}
// Example: fetch exchange rate CSV from a data provider
try {
const rates = await fetchCsvAsJson('https://data.ecb.internal/rates/daily.csv')
console.log(JSON.stringify(rates.slice(0, 3), null, 2))
// Send as JSON to downstream service
await fetch('https://api.internal/v2/rates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ data: rates }),
})
} catch (err) {
console.error('Rate sync failed:', err.message)
}JSON.stringify() به شما اجازه میدهد ستونهای خاصی از CSV را در لیست سفید قرار دهید. یک آرایه از نام سرستونها بگذارید تا فقط آن فیلدها را شامل کنید: JSON.stringify(rows, ['name', 'email', 'department']). خصوصیات غیر موجود در آرایه بیسروصدا از خروجی حذف میشوند.تبدیل CSV به JSON از خط فرمان
Node.js میتواند اسکریپتهای inline اجرا کند، و ابزارهای CLI اختصاصی وجود دارند که تبدیل CSV-به-JSON را بدون نوشتن اسکریپت انجام میدهند.
# Pipe CSV to a Node.js inline script
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 is a Swiss Army knife for structured data # Install: brew install miller (macOS) or apt install miller (Debian/Ubuntu) mlr --icsv --ojson cat inventory.csv # Filter rows during conversion mlr --icsv --ojson filter '$quantity > 100' inventory.csv # Select specific columns mlr --icsv --ojson cut -f sku,warehouse,quantity inventory.csv
# Install globally npm install -g csvtojson # Convert file csvtojson servers.csv > servers.json # Pipe from stdin cat exports/q1-metrics.csv | csvtojson > q1-metrics.json
برای فایلهای بزرگ، Miller معمولاً انتخاب بهتری نسبت به csvtojson است. Miller در C پیادهسازی شده و CSV را بهصورت stream بدون بارگذاری کل فایل در حافظه پردازش میکند، یعنی صادرات چند گیگابایتی را با مصرف حافظه ثابت مدیریت میکند. همچنین از عملیاتهای درجا در سطح فیلد پشتیبانی میکند — تغییر نام ستونها، تبدیل نوع مقادیر، فیلتر ردیفها — قبل از اینکه داده به JSON تبدیل شود، بنابراین از یک pipeline دو مرحلهای parse-سپس-تبدیل جلوگیری میکنید. csvtojson، ولی، در Node.js اجرا میشود و وقتی بقیه زنجیره ابزار شما JavaScript است راحتتر است: میتوانید خروجی آن را مستقیماً به streamهای Node پایپ کنید، آن را بهعنوان کتابخانه import کنید، یا از colParser API آن برای تبدیل نوع به ازای هر ستون در کد استفاده کنید. Miller را برای توان عملیاتی خام و pipelineهای shell ترجیح دهید؛ csvtojson را وقتی نیاز به یکپارچگی تنگ با اپلیکیشن Node.js دارید ترجیح دهید.
jq بهطور بومی CSV تجزیه نمیکند. اگر به jq در pipeline نیاز دارید، ابتدا با csvtojson یا mlr به JSON تبدیل کنید، سپس خروجی JSON را برای فیلتر و تبدیل به jq پایپ کنید.جایگزین پرکارایی — PapaParse
رویکرد دستی split(',') روی فایلهای CSV دنیای واقعی شکست میخورد. فیلدهای نقلقولدار حاوی کاما، newlineهای تعبیهشده، نقلقول دوگانه escapeشده — همه اینها یک تقسیمکننده ساده را میشکنند. PapaParse کتابخانهای است که وقتی CSV از یک منبع ناشناخته میآید به آن مراجعه میکنم. هر موارد لبهای RFC 4180 را مدیریت میکند، جداکنندهها را تشخیص میدهد، و در هر دو Node.js و مرورگر کار میکند.
npm install papaparse
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, // auto-converts numbers and booleans
skipEmptyLines: true,
transformHeader: h => h.trim().toLowerCase().replace(/\s+/g, '_'),
})
if (errors.length > 0) {
console.error('Parse errors:', 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} rows, delimiter: "${meta.delimiter}"`)گزینه dynamicTyping در PapaParse تبدیل نوع را بهصورت خودکار انجام میدهد — اعداد به اعداد تبدیل میشوند، "true"/"false" به boolean تبدیل میشوند. callback transformHeader نام ستونها را به snake_case نرمال میکند، که شما را از تعامل با سرستونهای ناسازگار از صادراتهای مختلف CSV نجات میدهد. برای تبدیلهای سریع بدون نوشتن کد تجزیه، مبدل CSV به JSON همه اینها را در مرورگر مدیریت میکند.
خروجی ترمینال با برجستهسازی نحو
ریختن یک آرایه JSON بزرگ در ترمینال خواندنش را سخت میکند. اضافه کردن برجستهسازی نحو به خروجی آن را در طول اشکالزدایی و توسعه خوانا میکند. پکیج cli-highlight خروجی JSON را در ترمینالهای Node.js رنگی میکند.
npm install cli-highlight
import { highlight } from 'cli-highlight'
// After converting CSV to JSON array
const jsonOutput = JSON.stringify(rows, null, 2)
// Print with syntax highlighting
console.log(highlight(jsonOutput, { language: 'json' }))
// Keys, strings, numbers, and booleans each get distinct colorsخروجی رنگی زمانی ارزشش را نشان میدهد که بهصورت تعاملی نتیجه یک تبدیل بزرگ را بررسی میکنید. کلیدهای JSON، مقادیر رشته، اعداد، و booleanها هر کدام رنگهای ANSI متمایزی دریافت میکنند، که تشخیص فیلدی با نوع اشتباه را آسان میکند — مثلاً شماره پورتی که باید 8080 باشد اما بهصورت رشته برجسته میشود زیرا تبدیل غیرفعال بود. این بهویژه هنگام اشکالزدایی فایلهای CSV صادرشده از ابزارهای صفحهگسترده مفید است که نوع ستونها در آنها در ردیفهای مختلف ناسازگار است. بدون رنگ، اسکن ۵۰ ردیف JSON برای یک فیلد با نوع اشتباه به معنای خواندن هر مقدار جداگانه است. با رنگ، یک عدد با رنگ رشته فوری به چشم میآید.
کار با فایلهای CSV بزرگ
بارگذاری یک فایل CSV 500 مگابایتی در یک رشته با readFileSync() حافظه را میخورد و احتمالاً فرآیند شما را crash میکند. برای فایلهای بزرگ، CSV را خط به خط stream کنید و آبجکتهای JSON را همانطور که میرسند emit کنید. پکیج csv-parse (بخشی از اکوسیستم csv در npm) یک تجزیهکننده streaming فراهم میکند که با streamهای Node.js کار میکند.
Streaming CSV به NDJSON با csv-parse
NDJSON (Newline-Delimited JSON) فرمتی است که هر خط فایل خروجی یک آبجکت JSON مستقل است. برخلاف یک آرایه JSON بزرگ واحد — که نیاز دارد کل فایل قبل از شروع خواندن در حافظه باشد — فایلهای NDJSON میتوانند خط به خط پردازش شوند. این NDJSON را برای مجموعه دادههای بزرگی که توسط پردازشگرهای log، pipelineهای stream، یا پایگاههای داده با APIهای bulk-import مصرف میشوند ایدهآل میکند. پکیج csv-parse یک آبجکت JavaScript به ازای هر ردیف CSV در حالت object mode emit میکند، بنابراین میتوانید آن را مستقیماً به یک transform stream پایپ کنید که بعد از هر JSON.stringify(row) علامت \n اضافه میکند.
import { createReadStream, createWriteStream } from 'node:fs'
import { parse } from 'csv-parse'
import { Transform } from 'node:stream'
import { pipeline } from 'node:stream/promises'
// Transform each CSV row object to a JSON line
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, // use first row as headers
skip_empty_lines: true,
trim: true,
cast: true, // auto-convert numbers and booleans
}),
toNdjson,
createWriteStream('telemetry-2026-03.ndjson')
)
console.log('Streaming conversion complete')
// Each line in the output file is one JSON object:
// {"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 برای مرورگر و Node.js
حالت streaming در PapaParse از یک callback step استفاده میکند که یک بار به ازای هر ردیف به جای جمعآوری تمام ردیفها در حافظه اجرا میشود. به آن یک Node.js ReadStream (در Node.js) یا یک آبجکت File (در مرورگر) میدهید و PapaParse chunking را داخلاً مدیریت میکند. هیچ pipeline stream راهاندازی نمیشود — فقط یک callback. وقتی به انطباق RFC 4180 بدون وارد کردن 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) {
// Process one row at a time — constant memory
rowCount++
if (result.data.quantity === 0) {
errors.push(`Row ${rowCount}: ${result.data.sku} is out of stock`)
}
},
complete() {
console.log(`Processed ${rowCount} rows`)
if (errors.length > 0) {
console.log(`Issues found: ${errors.length}`)
errors.forEach(e => console.log(` ${e}`))
}
},
error(err) {
console.error('Parse failed:', err.message)
},
})اشتباهات رایج
مشکل: CSV، JSON نیست. ارسال یک رشته CSV خام به JSON.parse() یک SyntaxError پرتاب میکند زیرا کاما و newline نحو JSON معتبری نیستند.
راهحل: ابتدا CSV را با استفاده از split() یا یک کتابخانه به آبجکتهای JavaScript تجزیه کنید، سپس از JSON.stringify() برای تولید JSON استفاده کنید. فقط روی رشتههایی که از قبل JSON معتبر هستند JSON.parse() فراخوانی کنید.
const csv = 'name,email\nعلی رضایی,ali@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) // valid JSON stringconst csv = 'name,email\nعلی رضایی,ali@nexuslabs.io' const data = JSON.parse(csv) // SyntaxError: Unexpected token 'a'
مشکل: فراخوانی toString() روی یک آبجکت JavaScript رشته بیفایده '[object Object]' به جای دادههای واقعی برمیگرداند. این خروجی CSV-به-JSON شما را بیسروصدا نابود میکند.
راهحل: همیشه از JSON.stringify() برای تبدیل آبجکتهای JavaScript به رشتههای JSON استفاده کنید. toString() برای تبدیل primitive به رشته وجود دارد، نه برای serialization.
const row = { server: 'api-gateway', port: 8080 }
const output = JSON.stringify(row, null, 2)
// '{"server":"api-gateway","port":8080}'const row = { server: 'api-gateway', port: 8080 }
const output = row.toString()
// "[object Object]" — data is goneمشکل: یک split(",") ساده وقتی مقادیر CSV حاوی کاما داخل فیلدهای نقلقولدار هستند میشکند: "Widget, Large" به جای یک مقدار به دو مقدار جداگانه تبدیل میشود.
راهحل: برای هر داده CSV که کاملاً کنترل نمیکنید از PapaParse یا csv-parse استفاده کنید. اگر باید بهصورت دستی تجزیه کنید، یک تجزیهکننده ماشین حالت پیادهسازی کنید که ردیابی میکند موقعیت فعلی داخل فیلد نقلقولدار است یا نه.
import Papa from 'papaparse'
const { data } = Papa.parse('"Widget, Large","Premium quality",29.99')
// data[0] = ["Widget, Large", "Premium quality", "29.99"]
// 3 values, correctly parsedconst line = '"Widget, Large","Premium quality",29.99'
const values = line.split(',')
// ["\"Widget", " Large\"", "\"Premium quality\"", "29.99"]
// 4 values instead of 3 — first field split incorrectlyمشکل: بدون تبدیل نوع، port: "8080" بهصورت رشته در JSON باقی میماند به جای عدد. سیستمهای downstream که نوعهای عددی انتظار دارند داده را رد میکنند یا اشتباه مدیریت میکنند.
راهحل: تبدیل نوع صریح را در طول مرحله نگاشت اعمال کنید، یا از PapaParse با dynamicTyping: true استفاده کنید. همیشه در مورد اینکه کدام فیلدها باید عددی باشند آگاهانه تصمیم بگیرید.
const row = {
port: Number('8443'), // 8443
debug: 'true' === 'true', // true
workers: Number('4'), // 4
}
JSON.stringify(row)
// {"port":8443,"debug":true,"workers":4} — correct typesconst row = { port: '8443', debug: 'true', workers: '4' }
JSON.stringify(row)
// {"port":"8443","debug":"true","workers":"4"} — all stringsتجزیه دستی در مقابل کتابخانهها — مقایسه سریع
برای اسکریپتهای سریع که فرمت CSV را کنترل میکنید و میدانید فیلد نقلقولداری وجود ندارد، رویکرد داخلی split() + JSON.stringify() کار میکند و هیچ وابستگی نیاز ندارد. برای سیستمهای تولیدی که فایلهای CSV آپلودشده توسط کاربر را پردازش میکنند، از PapaParse در مرورگر یا csv-parse در Node.js استفاده کنید — هر دو RFC 4180 را بهدرستی مدیریت میکنند و از streaming پشتیبانی میکنند. پکیج csvtojson تنها پکیجی است که JSON را مستقیماً خروجی میدهد و هم تجزیه و هم serialization را در یک فراخوانی مدیریت میکند. وقتی سریعترین مسیر از paste-به-نتیجه را میخواهید، مبدل CSV به JSON همه آن را در مرورگر بدون هیچ راهاندازی مدیریت میکند.
سوالات متداول
چگونه بدون کتابخانه CSV را در JavaScript به JSON تبدیل کنم؟
رشته CSV را با newline تقسیم کنید تا ردیفها به دست آیند، سرستونها را از اولین ردیف با split(",") استخراج کنید، سپس ردیفهای باقیمانده را به آبجکتهایی با کلیدهای سرستون نگاشت کنید. در نهایت JSON.stringify(array, null, 2) را برای تولید رشته JSON فرمتبندیشده فراخوانی کنید. این رویکرد برای فایلهای CSV سادهای که فرمتشان را کنترل میکنید و میدانید فیلد نقلقولدار یا کاما داخلی ندارند، مناسب است. برای دادههای صادرشده از صفحهگسترده یا سیستمهای خارجی، فیلدهای نقلقولدار و مقادیر چندخطی یک تقسیمکننده ساده را میشکنند — در آن موارد از PapaParse یا csv-parse استفاده کنید. برای فایلهای بسیار کوچک پردازششده در مرورگر، این رویکرد بدون وابستگی ایدهآل است.
const csv = `name,email,department
علی رضایی,ali@nexuslabs.io,Engineering
زهرا محمدی,zahra@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": "علی رضایی", "email": "ali@nexuslabs.io", "department": "Engineering" },
// { "name": "زهرا محمدی", "email": "zahra@nexuslabs.io", "department": "Product" }
// ]تفاوت JSON.stringify() و toString() برای آبجکتها چیست؟
فراخوانی toString() روی یک آبجکت ساده رشته بیمعنی "[object Object]" را برمیگرداند — هیچ اطلاعاتی از دادههای واقعی نمیدهد. JSON.stringify() یک رشته JSON معتبر با تمام کلیدها و مقادیر بهدرستی تبدیلشده تولید میکند، از جمله آبجکتها و آرایههای تودرتو. همیشه از JSON.stringify() استفاده کنید وقتی میخواهید یک آبجکت JavaScript (مثل یک ردیف مشتقشده از CSV) را به رشته JSON تبدیل کنید. برای معکوس کردن عملیات — بازسازی آبجکتهای زنده JavaScript از رشته JSON — از JSON.parse() استفاده کنید، که دقیقاً معکوس JSON.stringify() است. این دو تابع یک دور کامل را تشکیل میدهند: stringify برای ذخیره یا ارسال داده، parse برای مصرف آن.
const row = { name: 'علی رضایی', role: 'Engineer' }
console.log(row.toString()) // "[object Object]"
console.log(JSON.stringify(row)) // '{"name":"علی رضایی","role":"Engineer"}'چگونه فیلدهای CSV حاوی کاما یا نقلقول را مدیریت کنم؟
RFC 4180 مشخص میکند که فیلدهای حاوی کاما، newline یا نقلقول دوگانه باید در نقلقول دوگانه محاصره شوند و نقلقولهای تعبیهشده با دوگانهسازی آنها escape شوند ("" داخل فیلد نقلقولدار یک نقلقول واحد واقعی را نشان میدهد). یک split(",") دستی روی این فایلها میشکند — مرز فیلد دیگر فقط یک کاما ساده نیست. برای دادههای تولیدی از PapaParse یا csv-parse استفاده کنید، یا یک تجزیهکننده ماشین حالت بنویسید که ردیابی میکند آیا داخل فیلد نقلقولدار هستید یا نه. نوشتن یک ماشین حالت صحیح از صفر بهطور شگفتآوری پیچیده است: باید نقلقولها در ابتدای فیلد، نقلقولهای escapeشده در وسط فیلد، newlineها داخل فیلدهای نقلقولدار، و قراردادهای مختلف پایان خط (CRLF در مقابل LF) را مدیریت کنید. برای هر چیزی فراتر از داده CSV اسباببازی، از یک کتابخانه آزمودهشده استفاده کنید.
// PapaParse handles RFC 4180 correctly
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))
// description field correctly contains: A big "widget"آیا میتوانم مستقیماً در مرورگر CSV را به JSON تبدیل کنم؟
بله. هر دو JSON.stringify() و JSON.parse() در هر موتور مرورگری داخلی هستند. برای مرحله تجزیه CSV، میتوانید برای فایلهای ساده بر اساس newline و کاما تقسیم کنید، یا PapaParse را از طریق CDN وارد کنید (هیچ وابستگی Node.js ندارد). کل تبدیل سمت کلاینت اتفاق میافتد بدون هیچ رفتوبرگشتی به سرور، که برای حریم خصوصی فایل مفید است — دادههای CSV خام هرگز دستگاه کاربر را ترک نمیکنند. وقتی کاربر یک فایل CSV از طریق المنت <input type="file"> آپلود میکند، متد file.text() از File API یک Promise برمیگرداند که به محتوای فایل بهصورت رشته حل میشود و میتوانید آن را به تابع تبدیل خود ارسال کنید. این تبدیل CSV-به-JSON کاملاً درون مرورگر را برای داشبوردها، ابزارهای توسعهدهنده، و هر اپلیکیشنی که نیاز به پردازش دادههای آپلودشده بدون بکاند دارد، عملی میکند.
// Browser: user uploads a CSV file
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))
})چگونه مقادیر عددی و boolean را از CSV تجزیه کنم به جای اینکه همه چیز رشته بماند؟
CSV سیستم نوع ندارد — هر فیلد یک رشته است. باید مقادیر را در مرحله نگاشت تبدیل کنید. الگوهای عددی را با Number() یا parseFloat() بررسی کنید، "true"/"false" را به boolean تبدیل کنید، و رشتههای خالی را null در نظر بگیرید. مراقب فیلدهایی باشید که شبیه عدد به نظر میرسند اما باید بهصورت رشته باقی بمانند: کدپستیهایی مثل "۰۷۳۰۲" صفر پیشاهنگ خود را با Number() از دست میدهند، و شماره تلفن یا کدهای محصول با کاراکترهای عددی به همین ترتیب شکننده هستند. کتابخانه csvtojson تبدیل نوع خودکار را از طریق گزینه colParser انجام میدهد که به شما اجازه میدهد توابع تبدیل به ازای هر ستون مشخص کنید. گزینه dynamicTyping در PapaParse همان تبدیل را بهصورت جهانی در تمام ستونها اعمال میکند.
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
}
// Apply during CSV-to-object mapping
const row = { port: coerceValue('8443'), debug: coerceValue('true'), host: coerceValue('api.internal') }
// { port: 8443, debug: true, host: "api.internal" }چگونه خروجی CSV-به-JSON را در Node.js در فایل بنویسم؟
از fs.writeFileSync() با خروجی JSON.stringify() استفاده کنید. آرگومان سوم JSON.stringify تورفتگی را کنترل میکند — ۲ برای تورفتگی دو فاصله یا "\t" برای tab بگذارید. برای خواندن مجدد فایل، از JSON.parse(fs.readFileSync(path, "utf8")) استفاده کنید که آرایه زنده JavaScript از آبجکتها را بازسازی میکند. اگر در یک زمینه async فایل مینویسید (داخل یک تابع async یا در سطح بالای یک ماژول ES)، fs.promises.writeFile() را ترجیح دهید تا از مسدود کردن event loop هنگام تکمیل نوشتن فایل جلوگیری کنید. برای خروجیهای JSON بزرگ بیش از چند مگابایت، به جای ساخت کل رشته در حافظه قبل از نوشتن، پایپ کردن یک JSON stream به WriteStream را در نظر بگیرید.
import { writeFileSync, readFileSync } from 'node:fs'
// Write
const jsonOutput = JSON.stringify(rows, null, 2)
writeFileSync('employees.json', jsonOutput, 'utf8')
// Read back
const parsed = JSON.parse(readFileSync('employees.json', 'utf8'))
console.log(Array.isArray(parsed)) // true
console.log(parsed[0].name) // "علی رضایی"ابزارهای مرتبط
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.