- pandas.json_normalize() trong pandas 3.0 tự động flatten nested dict thành dot-separated columns, mở rộng list thành từng row qua record_path.
- Tham số errors='ignore' ngăn crash khi schema API không nhất quán - nhưng phải kiểm tra lại bằng df.isna().sum().
- Custom Python .get() nhanh hơn 3-5x khi chỉ cần 2-3 field từ JSON sâu nhiều cấp.
- jsonschema library giúp validate output đúng schema trước khi import hoặc forward đến API tiếp theo.
TL;DR
Khi chuyển dữ liệu giữa các API hoặc chuẩn bị JSON để import, schema không khớp sẽ phá vỡ pipeline. Bài tutorial trên freeCodeCamp của Nneoma Uche (tháng 7/2025) hướng dẫn hai cách clean và chuẩn hóa JSON data: pure Python và pandas, rồi xuất kết quả ra file theo schema định sẵn. Dataset thực hành: 200 bản ghi khách hàng tổng hợp.

Vấn đề với JSON lồng nhau
JSON tổ chức dữ liệu dạng cây phân cấp: object lồng trong object, array lồng trong object. DataFrame của pandas ngược lại: lưới 2 chiều nghiêm ngặt, mỗi ô phải là một scalar value.
Khi bạn gọi pd.DataFrame() với nested JSON, pandas không tự unpack. Kết quả là các cột chứa raw dict và list - không filter được, không join được, không aggregate được. Đây là điểm xuất phát của bài tutorial này.
Hai phương pháp song song
Tutorial cung cấp hai cách tiếp cận để transform cùng dataset (rename 4 field, xóa 2 field thừa, từ 6 field xuống còn 4):
Pure Python
- Import module
jsonvàtime, load file - Loop qua từng record, viết hàm rename field và loại bỏ field thừa
- Xuất ra file
.jsonmới
Ưu điểm: đơn giản, không cần thư viện bên ngoài, nhanh cho dataset nhỏ.
Pandas
- Extract list records trước khi load vào DataFrame (tránh lỗi từ nested/unrelated data)
- Dùng
pd.json_normalize()để flatten tự động - Apply custom function qua
.apply()hoặc list comprehension để rename field - Validate output bằng thư viện
jsonschema
Ưu điểm: có sẵn drop_duplicates(), dropna(), fillna() cho dữ liệu phức tạp, thiếu, hoặc trùng lặp.
Khai thác hết sức mạnh json_normalize()
Hàm pd.json_normalize() trong pandas 3.0 (tháng 1/2026) xử lý hầu hết công việc nặng. Các tham số quan trọng:
| Tham số | Mục đích | Ví dụ |
|---|---|---|
sep | Ký tự nối tên key lồng nhau | sep='_' tạo ra customer_city |
record_path | Expand array thành từng row riêng biệt | record_path='items' |
meta | Giữ context từ record cha vào các row con | meta=['order_id'] |
max_level | Giới hạn độ sâu flatten (chỉ ảnh hưởng dict) | max_level=1 |
errors='ignore' | Điền NaN thay vì crash khi thiếu key | Bắt buộc cho production ETL |
Cạm bẫy quan trọng nhất: max_level không có tác dụng gì với list. Nếu có array lồng nhau, bắt buộc dùng record_path hoặc .explode(). Nếu array lồng trong array (2 cấp), phải làm 2 bước: normalize outer list, rồi .explode() inner list, rồi normalize lại.
Bẫy thường gặp
- Orphaned child records: Dùng
record_pathmà quênmeta- mất toàn bộ context từ record cha. Luôn kết hợp cả hai. - Silent data loss:
errors='ignore'âm thầm nuốt missing data. Sau normalize luôn chạydf.isna().sum(). - Column name collision: Record con và cha có cùng tên key. Dùng
record_prefixhoặcmeta_prefixđể tránh ghi đè. - Schema không nhất quán: Field là string ở record này, list ở record kia -
json_normalizesẽ fail. Chuẩn hóa trước:field = field if isinstance(field, list) else [field].
Khi nào chọn phương pháp nào
| Tình huống | Lựa chọn |
|---|---|
| Dataset nhỏ, transform đơn giản | Pure Python |
| Cần full schema, ML / BI dashboard | Pandas json_normalize |
| Chỉ cần 2-3 field từ cấu trúc 8 cấp sâu | Custom Python .get() - nhanh hơn 3-5x |
| File > 1 GB | Chunked JSONL hoặc orjson |
| Schema thất thường, type không đồng nhất | Custom Python |
| Phân tích lặp lại nhiều lần | Convert sang Parquet - đọc nhanh hơn 10-50x |
Quy tắc vàng production: json_normalize cho 80% predictable, custom Python cho 20% irregular. Hai cách không loại trừ nhau.
Nguồn & Đọc thêm
Bài tutorial đầy đủ với code có thể chạy được: freeCodeCamp - How to Transform JSON Data to Match Any Schema (Nneoma Uche, tháng 7/2025).
Tài liệu chính thức: pandas.json_normalize docs | Let's Data Science - Flatten JSON to Pandas.

