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.

Transform JSON Data to Match Any Schema - freeCodeCamp

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 jsontime, load file
  • Loop qua từng record, viết hàm rename field và loại bỏ field thừa
  • Xuất ra file .json mớ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 đíchVí dụ
sepKý tự nối tên key lồng nhausep='_' tạo ra customer_city
record_pathExpand array thành từng row riêng biệtrecord_path='items'
metaGiữ context từ record cha vào các row conmeta=['order_id']
max_levelGiớ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 keyBắ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_path mà quên meta - 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ạy df.isna().sum().
  • Column name collision: Record con và cha có cùng tên key. Dùng record_prefix hoặc meta_prefix để tránh ghi đè.
  • Schema không nhất quán: Field là string ở record này, list ở record kia - json_normalize sẽ 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ốngLựa chọn
Dataset nhỏ, transform đơn giảnPure Python
Cần full schema, ML / BI dashboardPandas json_normalize
Chỉ cần 2-3 field từ cấu trúc 8 cấp sâuCustom Python .get() - nhanh hơn 3-5x
File > 1 GBChunked JSONL hoặc orjson
Schema thất thường, type không đồng nhấtCustom Python
Phân tích lặp lại nhiều lầnConvert 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.