Chuyển CSV sang JSON bằng Python — Hướng dẫn json.dumps()

·Backend Developer·Đánh giá bởiPriya Sharma·Đã xuất bản

Sử dụng Chuyển CSV sang JSON miễn phí trực tiếp trên trình duyệt — không cần cài đặt.

Dùng thử Chuyển CSV sang JSON trực tuyến →

File CSV xuất hiện ở khắp nơi — báo cáo xuất ra, bản sao cơ sở dữ liệu, trích xuất log — và sớm hay muộn bạn cần chuyển đổi CSV đó sang JSON bằng Python. Thư viện chuẩn xử lý việc này với hai module: csv.DictReader chuyển mỗi hàng thành một dict Python, và json.dumps() chuyển đổi các dict đó thành chuỗi JSON. Để chuyển đổi nhanh mà không cần viết code,công cụ chuyển đổi CSV sang JSON thực hiện ngay lập tức trên trình duyệt. Hướng dẫn này đề cập toàn bộ quy trình lập trình: json.dump() vs json.dumps(), ghi JSON vào file, chuyển đổi dataclass, ép kiểu cho giá trị CSV, xử lý datetime và Decimal, và các phương pháp hiệu năng cao như orjson. Tất cả ví dụ hướng đến Python 3.10+.

  • csv.DictReader tạo ra một danh sách dict — chuyển đổi toàn bộ danh sách với json.dump(rows, f, indent=2) để ghi file JSON.
  • json.dump() ghi trực tiếp vào đối tượng file. json.dumps() trả về chuỗi. Chọn đúng cái và bạn tránh được một bản sao không cần thiết.
  • Giá trị CSV luôn là chuỗi. Ép kiểu các cột số tường minh bằng int(), float() trước khi chuyển đổi sang JSON.
  • Truyền ensure_ascii=False vào json.dumps() để giữ nguyên ký tự Unicode — tên có dấu, văn bản CJK — trong đầu ra.
  • Với datetime, UUID, hoặc Decimal từ CSV, dùng tham số default= với hàm dự phòng tùy chỉnh.
Before · json
After · json
order_id,product,quantity,price
ORD-7291,Wireless Keyboard,2,49.99
ORD-7292,USB-C Hub,1,34.50
[
  {
    "order_id": "ORD-7291",
    "product": "Wireless Keyboard",
    "quantity": "2",
    "price": "49.99"
  },
  {
    "order_id": "ORD-7292",
    "product": "USB-C Hub",
    "quantity": "1",
    "price": "34.50"
  }
]
Lưu ý:Lưu ý rằng quantity và price xuất hiện dưới dạng chuỗi JSON ("2", "49.99") trong đầu ra thô. CSV không có hệ thống kiểu — mọi giá trị đều là chuỗi. Cách khắc phục được đề cập trong phần ép kiểu bên dưới.

json.dumps() — Chuyển đổi Dict Python thành Chuỗi JSON

Module json đi kèm với mọi cài đặt Python — không cần pip install gì cả. json.dumps(obj) nhận một đối tượng Python (dict, list, chuỗi, số, bool, hoặc None) và trả về một str chứa JSON hợp lệ. Một từ điển Python trông tương tự một đối tượng JSON, nhưng chúng khác nhau về bản chất: dict là cấu trúc dữ liệu Python trong bộ nhớ, còn chuỗi JSON là văn bản đã được chuyển đổi. Gọi json.dumps() thu hẹp khoảng cách đó.

Ví dụ tối giản — Một hàng CSV thành JSON

Python 3.10+
import json

# Một hàng CSV được biểu diễn dưới dạng dict Python
server_entry = {
    "hostname": "web-prod-03",
    "ip_address": "10.0.12.47",
    "port": 8080,
    "region": "eu-west-1"
}

# Chuyển dict thành chuỗi JSON
json_string = json.dumps(server_entry)
print(json_string)
# {"hostname": "web-prod-03", "ip_address": "10.0.12.47", "port": 8080, "region": "eu-west-1"}
print(type(json_string))
# <class 'str'>

Kết quả là JSON thu gọn trên một dòng — tốt cho payload và lưu trữ, nhưng khó đọc. Thêm indent=2 để có đầu ra dễ đọc cho con người:

Python 3.10+ — pretty-printed output
import json

server_entry = {
    "hostname": "web-prod-03",
    "ip_address": "10.0.12.47",
    "port": 8080,
    "region": "eu-west-1"
}

pretty_json = json.dumps(server_entry, indent=2)
print(pretty_json)
# {
#   "hostname": "web-prod-03",
#   "ip_address": "10.0.12.47",
#   "port": 8080,
#   "region": "eu-west-1"
# }

Hai tham số khác tôi dùng trong hầu hết mọi lần gọi: sort_keys=True sắp xếp các khóa từ điển theo thứ tự bảng chữ cái (rất hữu ích để so sánh file JSON qua các phiên bản), và ensure_ascii=False giữ nguyên các ký tự ngoài ASCII thay vì thoát chúng thành chuỗi \uXXXX.

Python 3.10+ — sort_keys and ensure_ascii
import json

warehouse_record = {
    "sku": "WH-9031",
    "location": "Kho Hà Nội 3",
    "quantity": 240,
    "last_audit": "2026-03-10"
}

output = json.dumps(warehouse_record, indent=2, sort_keys=True, ensure_ascii=False)
print(output)
# {
#   "last_audit": "2026-03-10",
#   "location": "Kho Hà Nội 3",
#   "quantity": 240,
#   "sku": "WH-9031"
# }

Lưu ý nhanh về tham số separators: mặc định là (", ", ": ") — thêm khoảng trắng sau dấu phẩy và dấu hai chấm. Để có đầu ra thu gọn nhất có thể (hữu ích khi nhúng JSON vào tham số URL hoặc tiết kiệm byte trong phản hồi API), truyền separators=(",", ":").

Lưu ý:Một dict Python và một đối tượng JSON trông gần như giống hệt nhau khi in ra. Sự khác biệt: json.dumps() chuyển Python True thành JSON true, None thành null, và bao chuỗi trong dấu nháy kép (Python cho phép nháy đơn, JSON thì không). Luôn dùng json.dumps() để tạo JSON hợp lệ — không dùngstr() hay repr().

csv.DictReader sang File JSON — Quy Trình Hoàn Chỉnh

Tác vụ thực tế phổ biến nhất là đọc toàn bộ file CSV và lưu thành JSON. Đây là script hoàn chỉnh trong chưa đến 10 dòng. csv.DictReader tạo ra một iterator của các đối tượng dict — một đối tượng mỗi hàng, dùng dòng đầu tiên làm khóa. Bao nó trong list() thu thập tất cả hàng vào một danh sách Python, được chuyển đổi thành mảng JSON.

Python 3.10+ — full CSV to JSON conversion
import csv
import json

# Bước 1: Đọc các hàng CSV vào danh sách dict
with open("inventory.csv", "r", encoding="utf-8") as csv_file:
    rows = list(csv.DictReader(csv_file))

# Bước 2: Ghi danh sách thành file JSON
with open("inventory.json", "w", encoding="utf-8") as json_file:
    json.dump(rows, json_file, indent=2, ensure_ascii=False)

print(f"Đã chuyển đổi {len(rows)} hàng thành inventory.json")

Hai lần gọi open(): một để đọc CSV, một để ghi JSON. Đó là toàn bộ mẫu. Lưu ý rằng đây dùng json.dump() (không có chữ s) — nó ghi trực tiếp vào file handle. Dùng json.dumps() sẽ trả về một chuỗi mà sau đó bạn cần ghi riêng bằng f.write(). json.dump() hiệu quả hơn về bộ nhớ vì nó truyền đầu ra thay vì xây dựng toàn bộ chuỗi trong bộ nhớ trước.

Khi bạn cần JSON dưới dạng chuỗi thay vì file — để nhúng vào payload API, in ra stdout, hoặc chèn vào cột cơ sở dữ liệu — chuyển sang json.dumps():

Python 3.10+ — CSV rows as JSON string
import csv
import json

with open("sensors.csv", "r", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))

# Lấy JSON dưới dạng chuỗi thay vì ghi vào file
json_payload = json.dumps(rows, indent=2)
print(json_payload)
# [
#   {
#     "sensor_id": "TMP-4401",
#     "location": "Tòa nhà 7 - Tầng 2",
#     "reading": "22.4",
#     "unit": "celsius"
#   },
#   ...
# ]

Một hàng so với toàn bộ tập dữ liệu: nếu bạn gọi json.dumps(single_dict) bạn nhận được một đối tượng JSON ({...}). Gọi json.dumps(list_of_dicts) bạn nhận được một mảng JSON ([{...}, {...}]). Hình dạng container bên ngoài phụ thuộc vào những gì bạn truyền vào. Hầu hết các đích tiêu thụ hạ nguồn kỳ vọng một mảng cho dữ liệu dạng bảng.

Xử Lý Giá Trị Không Phải Chuỗi — Ép Kiểu từ CSV

Đây là điều khiến mọi người bị bắt lần đầu tiên: csv.DictReader trả về mọi giá trị dưới dạng chuỗi. Số 42 trong CSV của bạn trở thành chuỗi "42" trong dict. Nếu bạn chuyển đổi trực tiếp với json.dumps(), JSON của bạn sẽ có "quantity": "42" thay vì "quantity": 42. Các API kiểm tra kiểu dữ liệu sẽ từ chối điều này. Bạn cần ép kiểu tường minh.

Python 3.10+ — type coercion for CSV rows
import csv
import json

def coerce_types(row: dict) -> dict:
    """Chuyển đổi giá trị chuỗi sang kiểu Python phù hợp."""
    return {
        "sensor_id": row["sensor_id"],
        "location": row["location"],
        "temperature": float(row["temperature"]),
        "humidity": float(row["humidity"]),
        "battery_pct": int(row["battery_pct"]),
        "active": row["active"].lower() == "true",
    }

with open("sensor_readings.csv", "r", encoding="utf-8") as f:
    rows = [coerce_types(row) for row in csv.DictReader(f)]

print(json.dumps(rows[0], indent=2))
# {
#   "sensor_id": "TMP-4401",
#   "location": "Tòa nhà 7 - Tầng 2",
#   "temperature": 22.4,
#   "humidity": 58.3,
#   "battery_pct": 87,
#   "active": true
# }

Bây giờ temperature là số thực, battery_pct là số nguyên, và active là boolean trong đầu ra JSON. Hàm ép kiểu dành riêng cho schema CSV của bạn — không có cách chung nào để đoán kiểu từ dữ liệu CSV, vì vậy tôi viết một hàm cho mỗi định dạng CSV.

Chuyển Đổi Đối Tượng Tùy Chỉnh và Các Kiểu Không Chuẩn

Module json của Python không thể chuyển đổi datetime, UUID, Decimal, hoặc các lớp tùy chỉnh ngay lập tức. Gọi json.dumps() trên bất kỳ cái nào trong số này sẽ raise TypeError. Có hai cách xử lý.

Cách 1: Tham số default=

Truyền một hàm vào default= để chuyển đổi các kiểu không xác định thành thứ gì đó có thể chuyển đổi. Hàm này chỉ được gọi cho các đối tượng mà bộ mã hóa JSON không biết cách xử lý.

Python 3.10+ — default= for datetime, UUID, Decimal
import json
from datetime import datetime
from decimal import Decimal
from uuid import UUID

def json_serial(obj):
    """Bộ chuyển đổi dự phòng cho các kiểu không chuẩn."""
    if isinstance(obj, datetime):
        return obj.isoformat()
    if isinstance(obj, UUID):
        return str(obj)
    if isinstance(obj, Decimal):
        return float(obj)
    raise TypeError(f"Type {type(obj).__name__} is not JSON serializable")

transaction = {
    "txn_id": UUID("a1b2c3d4-e5f6-7890-abcd-ef1234567890"),
    "amount": Decimal("149.99"),
    "currency": "EUR",
    "processed_at": datetime(2026, 3, 15, 14, 30, 0),
    "gateway": "stripe",
}

print(json.dumps(transaction, indent=2, default=json_serial))
# {
#   "txn_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
#   "amount": 149.99,
#   "currency": "EUR",
#   "processed_at": "2026-03-15T14:30:00",
#   "gateway": "stripe"
# }
Cảnh báo:Luôn raise TypeError ở cuối hàm default= của bạn cho các kiểu không nhận ra. Nếu bạn trả về None hoặc bỏ qua chúng một cách âm thầm, bạn sẽ nhận được null trong đầu ra mà không có dấu hiệu nào cho thấy dữ liệu đã bị mất.

Cách 2: Dataclass với asdict()

Python dataclass cung cấp định nghĩa kiểu đúng cho các hàng CSV của bạn. Dùng dataclasses.asdict() để chuyển đổi một thể hiện dataclass thành dict thuần, sau đó truyền vào json.dumps().

Python 3.10+ — dataclass serialization
import json
from dataclasses import dataclass, asdict
from datetime import datetime

@dataclass
class ShipmentRecord:
    tracking_id: str
    origin: str
    destination: str
    weight_kg: float
    shipped_at: datetime

def json_serial(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Not serializable: {type(obj).__name__}")

shipment = ShipmentRecord(
    tracking_id="SHP-9827",
    origin="Hà Nội",
    destination="TP. Hồ Chí Minh",
    weight_kg=1240.5,
    shipped_at=datetime(2026, 3, 12, 8, 0, 0),
)

print(json.dumps(asdict(shipment), indent=2, default=json_serial))
# {
#   "tracking_id": "SHP-9827",
#   "origin": "Hà Nội",
#   "destination": "TP. Hồ Chí Minh",
#   "weight_kg": 1240.5,
#   "shipped_at": "2026-03-12T08:00:00"
# }
Lưu ý:asdict() đệ quy chuyển đổi các dataclass lồng nhau thành dict. Nếu dataclass của bạn chứa danh sách các dataclass khác, toàn bộ cây sẽ được chuyển đổi — không cần code bổ sung.

Tham Khảo Tham Số json.dumps()

Danh sách đầy đủ các đối số từ khóa được chấp nhận bởi json.dumps() json.dump(). Cả hai hàm chấp nhận các tham số giống hệt nhau — json.dump() nhận thêm một đối số đầu tiên cho đối tượng file.

Tham số
Kiểu
Mặc định
Mô tả
obj
Any
(bắt buộc)
Đối tượng Python cần chuyển đổi — dict, list, str, int, float, bool, None
indent
int | str | None
None
Số khoảng trắng (hoặc chuỗi) cho mỗi cấp thụt lề. None = đầu ra thu gọn trên một dòng
sort_keys
bool
False
Sắp xếp các khóa từ điển theo thứ tự bảng chữ cái trong đầu ra
ensure_ascii
bool
True
Thoát tất cả ký tự ngoài ASCII thành \\uXXXX. Đặt False để xuất trực tiếp UTF-8
default
Callable | None
None
Hàm được gọi cho các đối tượng không thể chuyển đổi mặc định — trả về giá trị có thể chuyển đổi hoặc raise TypeError
separators
tuple[str, str] | None
None
Ghi đè (item_separator, key_separator). Dùng (",", ":") để xuất thu gọn không có khoảng trắng
skipkeys
bool
False
Bỏ qua các khóa dict không phải str, int, float, bool, hoặc None thay vì raise TypeError
allow_nan
bool
True
Cho phép float("nan"), float("inf"), float("-inf"). Đặt False để raise ValueError với các giá trị này
cls
Type[JSONEncoder] | None
None
Lớp con JSONEncoder tùy chỉnh thay thế lớp mặc định

csv.DictReader — Đọc CSV vào Dict Python

csv.DictReader là nửa còn lại của pipeline CSV sang JSON. Nó bao bọc một đối tượng file và tạo ra một dict cho mỗi hàng, dùng dòng đầu tiên làm tên trường. So với csv.reader (tạo ra các danh sách thuần), DictReader cung cấp truy cập theo tên vào các cột — không có chỉ số khó hiểu như row[3].

Python 3.10+ — DictReader with custom delimiter
import csv
import json

# File phân tách bằng tab từ xuất cơ sở dữ liệu
with open("user_sessions.tsv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f, delimiter="\t")
    sessions = list(reader)

print(json.dumps(sessions[:2], indent=2))
# [
#   {
#     "session_id": "sess_8f2a91bc",
#     "user_id": "usr_4421",
#     "started_at": "2026-03-15T09:12:00Z",
#     "duration_sec": "342",
#     "pages_viewed": "7"
#   },
#   {
#     "session_id": "sess_3c7d44ef",
#     "user_id": "usr_1187",
#     "started_at": "2026-03-15T09:14:22Z",
#     "duration_sec": "128",
#     "pages_viewed": "3"
#   }
# ]
Cảnh báo:csv.DictReader đọc toàn bộ file theo kiểu lười biếng — nó tạo ra từng hàng một. Gọi list(reader) tải tất cả hàng vào bộ nhớ. Với các file có hàng triệu hàng, hãy xử lý hàng theo kiểu truyền phát thay vì thu thập tất cả.

Chuyển Đổi CSV từ File và Phản Hồi API

Hai tình huống thực tế: đọc file CSV từ ổ đĩa và chuyển đổi, và lấy dữ liệu CSV từ một endpoint API (nhiều dịch vụ báo cáo trả về CSV). Cả hai đều cần xử lý lỗi đúng cách.

Đọc File CSV → Chuyển đổi → Ghi JSON

Python 3.10+ — file conversion with error handling
import csv
import json
import sys

def csv_to_json_file(csv_path: str, json_path: str) -> int:
    """Chuyển đổi file CSV sang JSON. Trả về số hàng đã ghi."""
    try:
        with open(csv_path, "r", encoding="utf-8") as f:
            rows = list(csv.DictReader(f))
    except FileNotFoundError:
        print(f"Lỗi: {csv_path} không tìm thấy", file=sys.stderr)
        sys.exit(1)
    except csv.Error as e:
        print(f"Lỗi phân tích CSV trong {csv_path}: {e}", file=sys.stderr)
        sys.exit(1)

    with open(json_path, "w", encoding="utf-8") as f:
        json.dump(rows, f, indent=2, ensure_ascii=False)

    return len(rows)

count = csv_to_json_file("fleet_vehicles.csv", "fleet_vehicles.json")
print(f"Đã ghi {count} bản ghi vào fleet_vehicles.json")

Lấy CSV từ API → Phân tích → JSON

Python 3.10+ — API CSV response to JSON
import csv
import io
import json
import urllib.request

def fetch_csv_as_json(url: str) -> str:
    """Lấy CSV từ URL và trả về dưới dạng chuỗi JSON."""
    try:
        with urllib.request.urlopen(url, timeout=10) as resp:
            raw = resp.read().decode("utf-8")
    except urllib.error.URLError as e:
        raise RuntimeError(f"Failed to fetch {url}: {e}")

    reader = csv.DictReader(io.StringIO(raw))
    rows = list(reader)

    if not rows:
        raise ValueError("CSV response was empty or had no data rows")

    return json.dumps(rows, indent=2, ensure_ascii=False)

# Ví dụ: endpoint xuất trả về CSV
try:
    result = fetch_csv_as_json("https://reports.internal/api/v2/daily-metrics.csv")
    print(result)
except (RuntimeError, ValueError) as e:
    print(f"Error: {e}")

Cả hai ví dụ đều dùng encoding="utf-8" tường minh trên mọi lần mở file. Điều này quan trọng với các file CSV chứa ký tự ngoài ASCII — tên có dấu, địa chỉ với ký tự đặc biệt, văn bản CJK. Không có mã hóa tường minh, Python sẽ dùng mặc định của hệ thống, trên Windows thường là cp1252 và sẽ làm hỏng các ký tự nhiều byte một cách âm thầm.

Xác Minh Đầu Ra JSON với json.loads()

Sau khi chuyển đổi CSV sang chuỗi JSON, bạn có thể xác minh kết quả bằng cách phân tích lại với json.loads(). Vòng lặp này phát hiện các vấn đề mã hóa, chuỗi thoát bị hỏng, hoặc nối chuỗi vô tình tạo ra JSON không hợp lệ. Bao lời gọi trong khối try/except.

Python 3.10+ — round-trip validation
import json

json_string = json.dumps({"order_id": "ORD-7291", "total": 129.99})

# Xác minh đây là JSON hợp lệ bằng cách phân tích lại
try:
    parsed = json.loads(json_string)
    print(f"JSON hợp lệ với {len(parsed)} khóa")
except json.JSONDecodeError as e:
    print(f"JSON không hợp lệ: {e}")
# JSON hợp lệ với 2 khóa

Chuyển Đổi CSV sang JSON qua Dòng Lệnh

Chuyển đổi nhanh từ terminal — không cần file script. Cờ -c của Python chạy code nội tuyến, và bạn có thể chuyển kết quả qua python3 -m json.tool để in đẹp.

bash — one-liner CSV to JSON
python3 -c "
import csv, json, sys
rows = list(csv.DictReader(sys.stdin))
json.dump(rows, sys.stdout, indent=2)
" < inventory.csv > inventory.json
bash — pipe CSV file and format with json.tool
python3 -c "import csv,json,sys; print(json.dumps(list(csv.DictReader(sys.stdin))))" < data.csv | python3 -m json.tool
bash — convert and validate with jq
python3 -c "import csv,json,sys; json.dump(list(csv.DictReader(sys.stdin)),sys.stdout)" < report.csv | jq .
Lưu ý:python3 -m json.tool là bộ định dạng JSON tích hợp sẵn. Nó đọc JSON từ stdin, xác thực và in với thụt lề 4 khoảng trắng. Hữu ích để xác minh rằng quá trình chuyển đổi CSV sang JSON của bạn tạo ra đầu ra hợp lệ. Nếu bạn muốn thụt lề 2 khoảng trắng hoặc cần lọc, dùng jq thay thế.

Giải Pháp Hiệu Năng Cao — orjson

Module json tích hợp hoạt động tốt cho hầu hết các file CSV. Nhưng nếu bạn xử lý tập dữ liệu với hàng chục nghìn hàng trong một vòng lặp, hoặc API của bạn cần chuyển đổi dữ liệu có nguồn gốc từ CSV cho mỗi yêu cầu, orjson nhanh hơn 5–10 lần. Nó được viết bằng Rust, trả về bytes thay vì str, và tự nhiên chuyển đổi datetime, UUID, và mảng numpy mà không cần hàm default= tùy chỉnh.

bash — install orjson
pip install orjson
Python 3.10+ — CSV to JSON with orjson
import csv
import orjson

with open("telemetry_events.csv", "r", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))

# orjson.dumps() trả về bytes, không phải str
json_bytes = orjson.dumps(rows, option=orjson.OPT_INDENT_2)

with open("telemetry_events.json", "wb") as f:  # lưu ý: "wb" cho bytes
    f.write(json_bytes)

print(f"Đã ghi {len(rows)} sự kiện ({len(json_bytes)} bytes)")

API hơi khác một chút: orjson.dumps() trả về bytes và dùng các cờ option= thay vì đối số từ khóa. Mở file ở chế độ ghi nhị phân ("wb") khi ghi đầu ra orjson. Nếu bạn cần chuỗi, gọi .decode("utf-8") trên kết quả.

Đầu Ra Terminal với Tô Màu Cú Pháp — rich

Gỡ lỗi quá trình chuyển đổi CSV sang JSON trong terminal dễ hơn với đầu ra có màu. Thư viện rich hiển thị JSON với tô màu cú pháp — khóa, chuỗi, số và boolean mỗi loại có màu riêng.

bash — install rich
pip install rich
Python 3.10+ — rich JSON output
import csv
import json
from rich.console import Console
from rich.syntax import Syntax

console = Console()

with open("deployment_log.csv", "r", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))

json_output = json.dumps(rows[:3], indent=2, ensure_ascii=False)
syntax = Syntax(json_output, "json", theme="monokai", line_numbers=True)
console.print(syntax)
Cảnh báo:rich thêm mã thoát ANSI vào đầu ra. Không ghi đầu ra định dạng rich vào file hoặc phản hồi API — nó sẽ chứa các ký tự điều khiển vô hình. Chỉ dùng rich để hiển thị trên terminal.

Làm Việc với File CSV Lớn

Tải file CSV 500 MB với list(csv.DictReader(f)) phân bổ toàn bộ tập dữ liệu trong bộ nhớ, sau đó json.dump() xây dựng toàn bộ chuỗi JSON trên đó. Với các file lớn hơn 50–100 MB, chuyển sang phương pháp truyền phát hoặc ghi NDJSON (JSON phân tách bằng dòng mới) — một đối tượng JSON mỗi dòng.

NDJSON — Một Đối Tượng JSON Mỗi Dòng

Python 3.10+ — streaming CSV to NDJSON
import csv
import json

def csv_to_ndjson(csv_path: str, ndjson_path: str) -> int:
    """Chuyển đổi CSV sang NDJSON, xử lý từng hàng một."""
    count = 0
    with open(csv_path, "r", encoding="utf-8") as infile, \
         open(ndjson_path, "w", encoding="utf-8") as outfile:
        for row in csv.DictReader(infile):
            outfile.write(json.dumps(row, ensure_ascii=False) + "\n")
            count += 1
    return count

rows_written = csv_to_ndjson("access_log.csv", "access_log.ndjson")
print(f"Đã ghi {rows_written} dòng vào access_log.ndjson")
# Mỗi dòng là một đối tượng JSON độc lập:
# {"timestamp":"2026-03-15T09:12:00Z","method":"GET","path":"/api/v2/orders","status":"200"}
# {"timestamp":"2026-03-15T09:12:01Z","method":"POST","path":"/api/v2/payments","status":"201"}

Truyền Phát với ijson cho Đầu Vào JSON Lớn

Python 3.10+ — ijson for reading large JSON
import ijson  # pip install ijson

def count_high_value_orders(json_path: str, threshold: float) -> int:
    """Đếm các đơn hàng trên ngưỡng mà không tải toàn bộ file."""
    count = 0
    with open(json_path, "rb") as f:
        for item in ijson.items(f, "item"):
            if float(item.get("total", 0)) > threshold:
                count += 1
    return count

# Xử lý file JSON 2 GB với mức sử dụng bộ nhớ cố định
high_value = count_high_value_orders("all_orders.json", 500.0)
print(f"Tìm thấy {high_value} đơn hàng trên $500")
Lưu ý:Chuyển sang NDJSON hoặc truyền phát khi CSV vượt quá 50–100 MB. ijson dùng để đọc lại các file JSON lớn — cho phía ghi, mẫu NDJSON ở trên giữ mức sử dụng bộ nhớ cố định bất kể kích thước file.

Lỗi Thường Gặp

Dùng json.dumps() rồi ghi vào file riêng

Vấn đề: json.dumps() trả về một chuỗi. Ghi nó bằng f.write() hoạt động nhưng tạo ra một chuỗi trung gian không cần thiết trong bộ nhớ — lãng phí cho tập dữ liệu lớn.

Cách sửa: Dùng json.dump(data, f) để ghi trực tiếp vào đối tượng file. Nó truyền đầu ra mà không xây dựng toàn bộ chuỗi trước.

Before · Python
After · Python
json_string = json.dumps(rows, indent=2)
with open("output.json", "w") as f:
    f.write(json_string)  # chuỗi trung gian không cần thiết
with open("output.json", "w", encoding="utf-8") as f:
    json.dump(rows, f, indent=2, ensure_ascii=False)  # ghi trực tiếp
Quên ép kiểu giá trị chuỗi CSV thành số

Vấn đề: csv.DictReader trả về tất cả giá trị dưới dạng chuỗi. Đầu ra JSON chứa "quantity": "5" thay vì "quantity": 5, điều này làm hỏng các đích tiêu thụ API có kiểm tra kiểu.

Cách sửa: Ép kiểu các cột số tường minh bằng int() hoặc float() trước khi chuyển đổi.

Before · Python
After · Python
rows = list(csv.DictReader(f))
json.dumps(rows)
# [{"port": "8080", "workers": "4"}]  ← chuỗi, không phải số
rows = list(csv.DictReader(f))
for row in rows:
    row["port"] = int(row["port"])
    row["workers"] = int(row["workers"])
json.dumps(rows)
# [{"port": 8080, "workers": 4}]  ← số nguyên đúng
Bỏ qua encoding='utf-8' khi mở file

Vấn đề: Trên Windows, mã hóa mặc định là cp1252. Các ký tự ngoài ASCII (tên có dấu, văn bản CJK) bị hỏng âm thầm hoặc raise UnicodeDecodeError.

Cách sửa: Luôn truyền encoding='utf-8' vào open() cho cả đọc CSV và ghi JSON.

Before · Python
After · Python
with open("locations.csv", "r") as f:  # dùng mã hóa mặc định của hệ thống
    rows = list(csv.DictReader(f))
with open("locations.csv", "r", encoding="utf-8") as f:
    rows = list(csv.DictReader(f))
Dùng str() hoặc repr() thay vì json.dumps()

Vấn đề: str(my_dict) tạo ra cú pháp Python (nháy đơn, True, None) không phải JSON hợp lệ. Các API và bộ phân tích JSON từ chối nó.

Cách sửa: Luôn dùng json.dumps() để tạo JSON hợp lệ. Nó chuyển True thành true, None thành null, và dùng dấu nháy kép.

Before · Python
After · Python
output = str({"active": True, "note": None})
# "{'active': True, 'note': None}"  ← KHÔNG phải JSON hợp lệ
output = json.dumps({"active": True, "note": None})
# '{"active": true, "note": null}'  ← JSON hợp lệ

json.dumps() vs Các Phương Pháp Khác — So Sánh Nhanh

Phương pháp
Đầu ra
JSON hợp lệ
Kiểu tùy chỉnh
Tốc độ
Cần cài đặt
json.dumps()
str
qua tham số default=
Cơ sở
Không (stdlib)
json.dump()
ghi vào file
qua tham số default=
Cơ sở
Không (stdlib)
csv.DictReader + json
str hoặc file
qua tham số default=
Cơ sở
Không (stdlib)
pandas to_json()
str hoặc file
✓ datetime tự nhiên
~2x nhanh hơn với dữ liệu lớn
pip install pandas
orjson.dumps()
bytes
✓ datetime/UUID tự nhiên
Nhanh hơn 5–10x
pip install orjson
dataclasses.asdict() + json
str
qua tham số default=
Cơ sở
Không (stdlib)
polars write_json()
str hoặc file
✓ datetime tự nhiên
~3x nhanh hơn với dữ liệu lớn
pip install polars

Đối với hầu hết các chuyển đổi CSV sang JSON, sự kết hợp thư viện chuẩn csv + json là lựa chọn đúng: không phụ thuộc, đi kèm Python, hoạt động mọi nơi. Chọn orjson khi phân tích hiệu năng cho thấy chuyển đổi là nút thắt cổ chai — sự khác biệt tốc độ là thực ở quy mô lớn. Dùng pandas khi bạn cũng cần làm sạch dữ liệu, lọc hoặc tổng hợp trước khi chuyển đổi sang JSON. Nếu bạn chỉ cần chuyển đổi nhanh mà không viết code,công cụ chuyển đổi CSV sang JSON trực tuyến xử lý ngay lập tức.

Câu Hỏi Thường Gặp

Sự khác biệt giữa json.dump() và json.dumps() trong Python là gì?

json.dump(obj, file) ghi đầu ra JSON trực tiếp vào một đối tượng file (bất cứ thứ gì có phương thức .write()). json.dumps(obj) trả về một chuỗi định dạng JSON. Dùng json.dump() khi ghi vào file, json.dumps() khi bạn cần JSON dưới dạng chuỗi Python để ghi log, nhúng vào payload, hoặc gửi qua socket. Cả hai đều chấp nhận cùng các đối số từ khóa (indent, sort_keys, ensure_ascii, default).

Làm thế nào để chuyển đổi một từ điển Python thành chuỗi JSON?

Gọi json.dumps(your_dict). Giá trị trả về là một str chứa JSON hợp lệ. Thêm indent=2 để có đầu ra dễ đọc. Nếu từ điển của bạn chứa các giá trị ngoài ASCII, truyền ensure_ascii=False để giữ nguyên các ký tự như chữ có dấu hoặc văn bản CJK.

Python 3.10+
import json

server_config = {"host": "api.internal", "port": 8443, "debug": False}
json_string = json.dumps(server_config, indent=2)
print(json_string)
# {
#   "host": "api.internal",
#   "port": 8443,
#   "debug": false
# }

Làm thế nào để lưu một danh sách dict Python thành file JSON?

Mở file ở chế độ ghi với mã hóa UTF-8, sau đó gọi json.dump(your_list, f, indent=2, ensure_ascii=False). Luôn dùng json.dump() (không phải json.dumps()) để xuất ra file — nó ghi trực tiếp vào file handle mà không tạo chuỗi trung gian trong bộ nhớ.

Python 3.10+
import json

records = [
    {"order_id": "ORD-4821", "total": 129.99, "currency": "USD"},
    {"order_id": "ORD-4822", "total": 89.50, "currency": "EUR"},
]

with open("orders.json", "w", encoding="utf-8") as f:
    json.dump(records, f, indent=2, ensure_ascii=False)

Tại sao json.dumps() chuyển True thành true và None thành null?

Các giá trị boolean Python (True, False) và None không phải là token JSON hợp lệ. Đặc tả JSON sử dụng chữ thường true, false và null. json.dumps() xử lý việc ánh xạ này tự động — True trở thành true, False trở thành false, None trở thành null. Bạn không cần chuyển đổi thủ công. Theo chiều ngược lại, json.loads() ánh xạ chúng trở lại kiểu Python.

Làm thế nào để xử lý đối tượng datetime khi chuyển đổi dữ liệu CSV sang JSON?

Truyền một hàm default= vào json.dumps() để chuyển đổi đối tượng datetime thành chuỗi ISO 8601. Hàm default được gọi cho bất kỳ đối tượng nào mà json không thể chuyển đổi tự nhiên. Trả về obj.isoformat() cho các thể hiện datetime và raise TypeError cho bất kỳ thứ gì khác.

Python 3.10+
import json
from datetime import datetime

def json_default(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Not serializable: {type(obj)}")

event = {"action": "login", "timestamp": datetime(2026, 3, 15, 9, 30, 0)}
print(json.dumps(event, default=json_default))
# {"action": "login", "timestamp": "2026-03-15T09:30:00"}

Có thể chuyển đổi CSV sang JSON mà không cần pandas không?

Có. Thư viện chuẩn Python có đủ mọi thứ bạn cần. Dùng csv.DictReader để đọc từng hàng thành một từ điển, thu thập các hàng vào một danh sách, và chuyển đổi với json.dump() hoặc json.dumps(). Không cần thư viện bên thứ ba. pandas chỉ đáng thêm vào nếu bạn cũng cần làm sạch dữ liệu, suy luận kiểu, hoặc đã dùng nó ở nơi khác trong dự án.

Python 3.10+
import csv
import json

with open("inventory.csv", "r", encoding="utf-8") as csv_file:
    rows = list(csv.DictReader(csv_file))

with open("inventory.json", "w", encoding="utf-8") as json_file:
    json.dump(rows, json_file, indent=2, ensure_ascii=False)

Để có giải pháp một click mà không cần viết Python, hãy thử công cụ chuyển đổi CSV sang JSON — dán dữ liệu CSV của bạn và nhận đầu ra JSON đã định dạng ngay lập tức.

Công Cụ Liên Quan

MS
Maria SantosBackend Developer

Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.

PS
Priya SharmaNgười đánh giá kỹ thuật

Priya is a data scientist and machine learning engineer who has worked across the full Python data stack — from raw data ingestion and cleaning to model deployment and monitoring. She is passionate about reproducible research, Jupyter-based workflows, and the practical engineering side of ML. She writes about NumPy, Pandas, data serialisation, and the Python patterns that make data pipelines reliable at scale.