JSON ↔ CSV: cột là gì, flatten thế nào (hiểu nhanh trước khi convert)

(Cập nhật: 19 tháng 7, 2026 ) JSON CSV flatten cột API Excel chuyển đổi
Kết luận

CSV = bảng phẳng (hàng × cột). JSON = cây. Convert chỉ “đúng” khi bạn quyết được: một hàng là object nào, và object lồng nhau flatten thành cột ra sao. Công cụ JSON ↔ CSV tự làm phẳng object bằng a.b, nhưng không bung mảng con thành nhiều hàng — hiểu quy tắc này trước khi paste Excel.

Sinh viên, freelancer và team outsourcing ở Việt Nam hay nhận file JSON từ Postman rồi hỏi: “Mở Excel thế nào?” Paste thẳng vào sheet thì vỡ. Convert online mà không hiểu cộtflatten thì header thành undefined, hoặc mất hết address.city.

Bài này không so sánh “khi nào chọn JSON hay CSV cho SME” dài dòng. Tập trung khái niệm cột + flatten ngắn — đủ để bạn đoán trước bảng sẽ ra sao trước khi bấm nút.

Ai cần đọc

  • Dev junior lần đầu xuất API response ra spreadsheet
  • Người nhận JSON từ đối tác và phải giao CSV cho kế toán
  • Ai từng thấy lỗi “Vui lòng nhập mảng JSON” mà không hiểu vì sao

Cột CSV là gì (nhìn từ JSON)

CSV không có object, không có mảng lồng. Chỉ có:

  1. Dòng 1 = tên cột (header)
  2. Mỗi dòng sau = một bản ghi
  3. Ô = giá trị text (có thể bọc " nếu chứa dấu phẩy)

Ánh xạ tư duy:

Trong JSONTrong CSV
Phần tử trong arrayMột hàng
Key ở cấp lá (sau flatten)Một cột
Giá trị primitive / chuỗi hóaMột ô

Ví dụ tối thiểu — hai object, cùng bộ key:

[
  {"name": "An", "city": "Đà Nẵng"},
  {"name": "Bình", "city": "Huế"}
]

→ Header: name,city2 cột, 2 hàng dữ liệu. Không cần flatten.

Nếu object thiếu key:

[
  {"name": "An", "city": "Đà Nẵng"},
  {"name": "Bình"}
]

→ Vẫn 2 cột (name, city). Hàng của Bình: ô city trống. Header là hợp mọi key xuất hiện trong mảng — đây là lý do bảng “phình” khi từng phần tử schema khác nhau.


Flatten ngắn: object lồng → cột dấu chấm

JSON hay có cây:

[
  {
    "id": 1,
    "user": { "name": "Lan", "email": "[email protected]" },
    "meta": { "source": "web" }
  }
]

CSV không giữ user là object. Flatten phổ biến (và đúng với công cụ Kawa):

CộtGiá trị
id1
user.nameLan
user.email[email protected]
meta.sourceweb

Quy tắc nhớ: mỗi đường dẫn tới lá = một cột. Độ sâu càng nhiều, header càng dài — vẫn đọc được trong Excel, nhưng pivot/filter theo user.* thì bạn phải quen tên cột có dấu chấm.

Object lồng vs mảng con

Flatten: object vs array
Cấu trúc Sau flatten (kiểu Kawa) Ý nghĩa
user: { name } Cột user.name An toàn, 1:1 theo đường dẫn
tags: ["a","b"] Một ô (chuỗi mảng) Không tách thành nhiều cột/hàng
items: [{ sku }] Một ô JSON string Không tự bung thành N hàng đơn hàng

Lỗi hay gặp: muốn “mỗi dòng = một dòng đơn hàng trong items[]” nhưng lại convert cả object order. Kết quả: một hàng order, cột items chứa cả mảng. Đúng hướng: lấy order.items (mảng) làm input — mỗi phần tử items mới là một hàng.


Vì sao phải là mảng?

Công cụ báo “Vui lòng nhập mảng JSON” khi bạn dán:

{ "id": 1, "name": "An" }

Object đơn = một bản ghi, nhưng không có “danh sách hàng”. Bọc lại:

[{ "id": 1, "name": "An" }]

API kiểu bọc:

{ "data": [ { "id": 1 }, { "id": 2 } ], "total": 2 }

→ Chỉ convert phần data. total không phải hàng — đừng ép cả object gốc thành CSV.


JSON → CSV trên UI (sau khi đã hiểu cột)

  1. Mở JSON ↔ CSV (chạy trên trình duyệt, không cần đăng ký)
  2. Dán mảng object (đã lấy đúng cấp hàng)
  3. Bấm JSON → CSV
  4. Đọc dòng header: có đủ user.name không? Có cột “rác” từ key lệch schema không?
  5. Sao chép kết quả → Excel / Google Sheets

Checklist 30 giây trước khi gửi file cho người khác:

  • Số hàng dữ liệu = số phần tử mảng?
  • Header có tên ổn định (không đổi mỗi lần vì object[0] thiếu key)?
  • Tiếng Việt trong ô còn đúng (UTF-8) khi mở bằng Sheets?
  • Không lộ PII nếu bạn share link tool trên máy công cộng — dữ liệu không upload, nhưng clipboard/màn hình vẫn lộ

CSV → JSON: cột trở lại key phẳng

Chiều ngược: dòng header thành tên property. Với header user.name, nhiều tool (kể cả convert đơn giản) tạo key đúng chuỗi "user.name"không tự dựng lại { user: { name } }.

id,user.name,active
1,Lan,true

→ Thường ra:

[
  { "id": "1", "user.name": "Lan", "active": "true" }
]

Hai điểm quan trọng:

  1. Kiểu: "1""true" là string — API cần number/boolean thì phải ép trong code
  2. Cấu trúc: muốn nested thật sự thì cần bước unflatten riêng, hoặc đổi header thành key phẳng cố ý (user_name)

Đây là lý do round-trip JSON→CSV→JSON hiếm khi bằng bản gốc từng byte.


Case ngắn: response “đẹp” nhưng cột nổ

Freelancer nhận:

[
  {
    "orderId": "VN-100",
    "customer": { "name": "Minh", "phone": "09x" },
    "items": [
      { "sku": "A1", "qty": 2 },
      { "sku": "B2", "qty": 1 }
    ]
  }
]

Convert cả object → 1 hàng, cột items dài. Kế toán cần 2 hàng sản phẩm.

Cách đúng khái niệm cột: flatten/export cấp items, gắn thêm orderId vào mỗi phần tử trước (map trong code hoặc chỉnh JSON tay):

[
  { "orderId": "VN-100", "sku": "A1", "qty": 2 },
  { "orderId": "VN-100", "sku": "B2", "qty": 1 }
]

→ 3 cột rõ, 2 hàng — đúng mô hình CSV.


Khi nào chưa nên convert

  • Schema mỗi phần tử khác nhau hoàn toàn → header hàng trăm cột thưa
  • Cần giữ hierarchy sâu để app đọc lại → giữ JSON, chỉ export subset
  • File cực lớn (chục MB) trên tab trình duyệt yếu → script Node/Python ổn định hơn

Còn lại: hiểu cột = key lá, hàng = phần tử mảng, rồi dùng JSON ↔ CSV là đủ cho đa số bài tập, ticket hỗ trợ và bàn giao nhanh với non-dev.

Liên kết liên quan