CSV에서 JSON으로의 변환은 개발자가 매일 직면하는 가장 일반적인 데이터 변환 작업 중 하나입니다. 시스템 간 데이터 마이그레이션, API 구축, 스프레드시트 처리 등 CSV를 JSON으로 변환하는 방법을 효율적으로 아는 것은 필수적입니다. 이 종합 가이드에서는 변환 도구, 파싱 알고리즘, JavaScript, Python, Bash 코드 예제 및 엣지 케이스 처리 모범 사례를 다룹니다.
무료 온라인 CSV to JSON 변환 도구를 사용해 보세요.
CSV란 무엇인가?
CSV는 Comma-Separated Values(쉼표로 구분된 값)의 약자로, RFC 4180에서 정의한 테이블 형식 데이터를 저장하는 일반 텍스트 파일 형식입니다. 각 행은 레코드를 나타내며, 값은 쉼표나 다른 구분자로 구분됩니다. 첫 번째 행은 일반적으로 헤더 역할을 합니다.
CSV 형식은 컴퓨팅 초기부터 사용되어 왔으며 단순함 때문에 여전히 인기가 있습니다. 모든 텍스트 편집기, 스프레드시트, 프로그래밍 언어에서 CSV를 읽고 쓸 수 있습니다. 단순하지만 CSV 파서는 인용 필드, 이스케이프된 따옴표, 여러 줄 값 등 까다로운 경우를 처리해야 합니다.
CSV와 JSON 사용 시기: CSV는 스프레드시트 내보내기, 데이터베이스 덤프 등 플랫 테이블 데이터에 적합합니다. JSON은 계층적 데이터 구조, API 응답, 설정 파일에 더 좋습니다.
CSV vs JSON: 상세 비교
CSV와 JSON의 차이를 이해하면 올바른 형식 선택과 변환 프로세스 이해에 도움이 됩니다:
| 특징 | CSV | JSON |
|---|---|---|
| 구조 | 플랫, 테이블 형식 | 계층적 (중첩 객체) |
| 가독성 | 간단한 데이터는 쉬움 | 포맷팅하면 읽기 쉬움 |
| 중첩 | 네이티브 미지원 | 완전 지원 |
| 데이터 타입 | 모두 문자열 | 문자열, 숫자, 불리언, null, 배열, 객체 |
| 파일 크기 | 일반적으로 작음 | 더 큼 (키 반복) |
| 사용 사례 | 스프레드시트, DB 내보내기 | API, 설정, NoSQL, 웹앱 |
CSV에서 JSON 변환 작동 원리
CSV to JSON 변환기 프로세스는 여러 단계를 포함합니다:
- 헤더 행 읽기: 열 이름을 추출하여 JSON 키로 사용.
- 각 데이터 행 파싱: 구분자로 분할하고 값을 헤더에 매핑.
- 인용 필드 처리: 큰따옴표로 둘러싼 값은 쉼표나 줄바꿈이 있어도 하나의 필드.
- 데이터 타입 감지: 숫자, 불리언, null 값 자동 변환.
- JSON 배열 구축: 각 행이 객체가 되고 모두 배열에 수집.
예시: CSV name,age,active\nAlice,30,true는 [{"name":"Alice","age":30,"active":true}]가 됩니다.
CSV to JSON 코드 예제
JavaScript: CSV to JSON 변환
CSV to JSON JavaScript 변환의 여러 접근법: 네이티브, Papa Parse, Node.js csv-parser:
// ===== Native JavaScript: CSV to JSON =====
function csvToJson(csv) {
const lines = csv.trim().split('\n');
const headers = lines[0].split(',').map(h => h.trim());
const result = [];
for (let i = 1; i < lines.length; i++) {
const values = lines[i].split(',');
const obj = {};
headers.forEach((header, index) => {
let val = values[index]?.trim() || '';
// Auto-detect types
if (val === 'true') val = true;
else if (val === 'false') val = false;
else if (val === 'null' || val === '') val = null;
else if (!isNaN(val) && val !== '') val = Number(val);
obj[header] = val;
});
result.push(obj);
}
return result;
}
const csv = `name,age,city,active
Alice,30,New York,true
Bob,25,London,false
Charlie,35,Tokyo,true`;
console.log(JSON.stringify(csvToJson(csv), null, 2));
// [
// { "name": "Alice", "age": 30, "city": "New York", "active": true },
// { "name": "Bob", "age": 25, "city": "London", "active": false },
// { "name": "Charlie", "age": 35, "city": "Tokyo", "active": true }
// ]
// ===== Papa Parse (Browser & Node.js) =====
// npm install papaparse
import Papa from 'papaparse';
// Parse CSV string
const result = Papa.parse(csvString, {
header: true, // Use first row as keys
dynamicTyping: true, // Auto-detect numbers and booleans
skipEmptyLines: true, // Ignore blank lines
});
console.log(result.data); // Array of JSON objects
console.log(result.errors); // Any parsing errors
console.log(result.meta); // Metadata (delimiter, fields, etc.)
// Parse CSV file (browser)
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', (e) => {
Papa.parse(e.target.files[0], {
header: true,
dynamicTyping: true,
complete: (results) => {
console.log(results.data); // JSON array
},
});
});
// ===== Node.js: csv-parser (streaming) =====
// npm install csv-parser
const csvParser = require('csv-parser');
const fs = require('fs');
const results = [];
fs.createReadStream('data.csv')
.pipe(csvParser())
.on('data', (row) => results.push(row))
.on('end', () => {
console.log(JSON.stringify(results, null, 2));
});Python: CSV to JSON 변환
CSV to JSON Python 변환: csv 모듈, pandas, json.dumps:
# ===== Python csv module =====
import csv
import json
# CSV string to JSON
csv_string = """name,age,city,active
Alice,30,New York,true
Bob,25,London,false"""
reader = csv.DictReader(csv_string.strip().splitlines())
data = list(reader)
json_output = json.dumps(data, indent=2)
print(json_output)
# CSV file to JSON file
with open('input.csv', 'r', encoding='utf-8') as csv_file:
reader = csv.DictReader(csv_file)
data = list(reader)
with open('output.json', 'w', encoding='utf-8') as json_file:
json.dump(data, json_file, indent=2, ensure_ascii=False)
# ===== pandas (recommended for large datasets) =====
import pandas as pd
# CSV to JSON with pandas
df = pd.read_csv('data.csv')
# Different JSON orientations
print(df.to_json(orient='records', indent=2)) # Array of objects
print(df.to_json(orient='columns', indent=2)) # Object of arrays
print(df.to_json(orient='index', indent=2)) # Object keyed by index
# With type conversion
df['age'] = pd.to_numeric(df['age'], errors='coerce')
df['active'] = df['active'].map({'true': True, 'false': False})
# Save to file
df.to_json('output.json', orient='records', indent=2, force_ascii=False)
# ===== Streaming large CSV files =====
import csv
import json
def csv_to_json_stream(csv_path, json_path, chunk_size=1000):
"""Convert large CSV to JSON using streaming."""
with open(json_path, 'w') as out:
out.write('[\n')
with open(csv_path, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
first = True
for row in reader:
if not first:
out.write(',\n')
json.dump(row, out, ensure_ascii=False)
first = False
out.write('\n]')
csv_to_json_stream('large_file.csv', 'output.json')Bash / 커맨드 라인: CSV to JSON
커맨드 라인에서 csvkit, miller, jq, awk로 변환:
# ===== csvkit: csvjson command =====
# pip install csvkit
# Basic CSV to JSON conversion
csvjson data.csv > output.json
# Indent output for readability
csvjson --indent 2 data.csv > output.json
# Specify a key column (creates object instead of array)
csvjson --key id data.csv > output.json
# ===== miller (mlr): powerful data processing =====
# brew install miller (macOS) or apt install miller (Linux)
# CSV to JSON
mlr --icsv --ojson cat data.csv > output.json
# CSV to JSON with filtering
mlr --icsv --ojson filter '$age > 25' data.csv
# CSV to JSON with field selection
mlr --icsv --ojson cut -f name,city data.csv
# ===== jq + awk: lightweight approach =====
# Convert simple CSV to JSON with awk
awk -F',' 'NR==1{split($0,h);next}
{printf "{";for(i=1;i<=NF;i++)
printf "%s\"%s\":\"%s\"",
(i>1?",":""),h[i],$i;print "}"}' data.csv | jq -s '.'
# ===== Using sed + jq for quick conversion =====
# Convert CSV to JSON (simple, no quoted fields)
head -1 data.csv | tr ',' '\n' > /tmp/headers.txt
tail -n +2 data.csv | while IFS=',' read -r col1 col2 col3; do
jq -n --arg a "$col1" --arg b "$col2" --arg c "$col3" \
'{name:$a, age:($b|tonumber), city:$c}'
done | jq -s '.'전용 CLI 도구: csvjson과 miller
csvjson(csvkit)과 miller(mlr)는 데이터 형식 변환 전용 커맨드 라인 도구입니다:
# ===== csvkit: full suite of CSV tools =====
# pip install csvkit
# View CSV statistics
csvstat data.csv
# Convert CSV to JSON
csvjson data.csv
# Convert Excel to CSV first, then to JSON
in2csv data.xlsx | csvjson > output.json
# Query CSV with SQL syntax, output as JSON
csvsql --query "SELECT name, age FROM data WHERE age > 25" data.csv | csvjson
# ===== miller (mlr): Swiss Army knife for data =====
# CSV to JSON (pretty-printed)
mlr --icsv --ojson --jflatsep '.' cat data.csv
# CSV to JSON with data transformation
mlr --icsv --ojson put '$full_name = $first . " " . $last' data.csv
# CSV to NDJSON (newline-delimited JSON, one object per line)
mlr --icsv --ojsonl cat data.csv
# Convert between any formats
mlr --icsv --ojson cat data.csv # CSV -> JSON
mlr --ijson --ocsv cat data.json # JSON -> CSV
mlr --icsv --otsv cat data.csv # CSV -> TSV
mlr --itsv --ojson cat data.tsv # TSV -> JSONJSON to CSV 변환 (역방향 프로세스)
역방향 프로세스인 JSON to CSV는 계층적 JSON 데이터를 플랫 테이블 구조로 변환합니다.
중첩 객체 플랫화: 점 표기법이나 밑줄로 펼침: user.name, user.address.city.
JavaScript와 Python에서의 JSON to CSV 변환 예제:
// ===== JavaScript: JSON to CSV =====
function jsonToCsv(jsonArray) {
if (!jsonArray.length) return '';
// Flatten nested objects
function flatten(obj, prefix = '') {
return Object.keys(obj).reduce((acc, key) => {
const fullKey = prefix ? prefix + '.' + key : key;
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
Object.assign(acc, flatten(obj[key], fullKey));
} else if (Array.isArray(obj[key])) {
acc[fullKey] = obj[key].join('|'); // Join arrays with pipe
} else {
acc[fullKey] = obj[key];
}
return acc;
}, {});
}
const flatData = jsonArray.map(item => flatten(item));
const headers = [...new Set(flatData.flatMap(Object.keys))];
const csvRows = [headers.join(',')];
for (const row of flatData) {
const values = headers.map(h => {
const val = row[h] ?? '';
// Quote values containing commas, quotes, or newlines
const str = String(val);
return str.includes(',') || str.includes('"') || str.includes('\n')
? '"' + str.replace(/"/g, '""') + '"'
: str;
});
csvRows.push(values.join(','));
}
return csvRows.join('\n');
}
// Example with nested JSON
const data = [
{ name: "Alice", address: { city: "NYC", zip: "10001" }, tags: ["dev", "admin"] },
{ name: "Bob", address: { city: "London", zip: "EC1A" }, tags: ["user"] },
];
console.log(jsonToCsv(data));
// name,address.city,address.zip,tags
// Alice,NYC,10001,dev|admin
// Bob,London,EC1A,user# ===== Python: JSON to CSV =====
import json
import csv
import pandas as pd
# Method 1: pandas (easiest)
with open('data.json') as f:
data = json.load(f)
df = pd.json_normalize(data, sep='.') # Flatten nested objects
df.to_csv('output.csv', index=False)
# Method 2: csv module (manual control)
def json_to_csv(json_data, csv_path):
"""Convert JSON array to CSV, handling nested objects."""
flat_data = [flatten_dict(item) for item in json_data]
fieldnames = list(dict.fromkeys(
key for item in flat_data for key in item.keys()
))
with open(csv_path, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(flat_data)
def flatten_dict(d, parent_key='', sep='.'):
items = []
for k, v in d.items():
new_key = f"{parent_key}{sep}{k}" if parent_key else k
if isinstance(v, dict):
items.extend(flatten_dict(v, new_key, sep).items())
elif isinstance(v, list):
items.append((new_key, '|'.join(str(i) for i in v)))
else:
items.append((new_key, v))
return dict(items)CSV 파싱 엣지 케이스 처리
견고한 CSV 파서는 수많은 엣지 케이스를 처리해야 합니다:
UTF-8 BOM: 일부 애플리케이션이 파일 시작에 보이지 않는 BOM을 추가합니다. 파서가 이를 제거해야 합니다.
구분자 변형: 유럽에서는 세미콜론, TSV에서는 탭. 좋은 파서는 자동 감지합니다.
누락된 값과 빈 필드: 후행 쉼표나 중간의 빈 필드. 빈 문자열이나 null로 유지해야 합니다.
여러 줄 필드: RFC 4180은 큰따옴표 안의 여러 줄 값을 허용합니다.
특수 문자와 이스케이프: 인용 필드 내 큰따옴표는 두 번 써서 이스케이프합니다.
불일치하는 행 길이: 견고한 파서는 짧은 행을 빈 값으로 채우거나 긴 행을 자릅니다.
// Robust CSV parser handling all edge cases
function parseCSV(text, delimiter = ',') {
// Strip UTF-8 BOM if present
if (text.charCodeAt(0) === 0xFEFF) {
text = text.slice(1);
}
const rows = [];
let row = [];
let field = '';
let inQuotes = false;
for (let i = 0; i < text.length; i++) {
const char = text[i];
const next = text[i + 1];
if (inQuotes) {
if (char === '"' && next === '"') {
field += '"'; // Escaped quote
i++; // Skip next quote
} else if (char === '"') {
inQuotes = false; // End of quoted field
} else {
field += char; // Regular char inside quotes
}
} else {
if (char === '"') {
inQuotes = true; // Start quoted field
} else if (char === delimiter) {
row.push(field);
field = '';
} else if (char === '\n' || (char === '\r' && next === '\n')) {
row.push(field);
rows.push(row);
row = [];
field = '';
if (char === '\r') i++; // Skip \n in \r\n
} else {
field += char;
}
}
}
// Push last field and row
if (field || row.length) {
row.push(field);
rows.push(row);
}
return rows;
}CSV 모범 사례
최대 호환성과 데이터 무결성을 위해 다음 모범 사례를 따르세요:
항상 UTF-8 인코딩 사용: 텍스트 인코딩의 유니버설 표준.
필드를 일관되게 인용: 가장 안전한 것은 모든 필드를 인용하는 것.
헤더 행 포함: 설명적인 이름과 일관된 명명 규칙으로.
일관된 구분자 사용: 파일 전체에 하나의 구분자.
큰 파일은 스트림 처리: 메모리를 초과하는 파일에 스트리밍 파서 사용.
변환 후 데이터 검증: 레코드 수, 데이터 타입, 무결성 확인.
자주 묻는 질문
CSV를 JSON으로 변환하려면?
헤더 행을 파싱하여 열 이름을 얻고, 각 행을 해당 키에 매핑합니다. Papa Parse(JavaScript)나 pandas(Python) 등의 라이브러리 또는 무료 온라인 도구를 사용할 수 있습니다.
CSV와 JSON의 차이점은?
CSV는 모든 값이 문자열인 플랫 테이블 형식입니다. JSON은 중첩 객체, 배열, 다양한 데이터 타입을 지원하는 계층적 형식입니다. CSV는 더 컴팩트하고, JSON은 더 표현력이 풍부합니다.
CSV는 중첩된 데이터를 처리할 수 있나요?
아닙니다. CSV는 네이티브로 중첩 구조를 지원하지 않습니다. 점 표기법, CSV 필드 내 JSON 인코딩, 별도의 CSV 파일 등으로 데이터를 플랫화해야 합니다.
CSV to JSON 변환은 개발자와 데이터 분석가의 기본 기술입니다. 무료 도구로 즉시 변환하세요.