JSON Toolkit

BOM có làm hỏng việc phân tích JSON không

Kết luận: BOM UTF-8 là ba byte vô hình, nên JSON.parse thất bại ở ký tự đầu và báo dòng 1 cột 1, làm tệp trông như rỗng hoặc bị cắt cụt.

Người mớiĐọc khoảng 4 phútXuất bản 2026-10-30Cập nhật 2026-10-30
Cách BOM làm hỏng việc phân tích JSON và cách loại bỏ nó

Tóm lại: hãy kiểm tra ba byte đầu xem có EF BB BF không và lưu lại dưới dạng UTF-8 không có BOM; trên máy chủ, hãy loại bỏ U+FEFF ở đầu trước khi phân tích bất kỳ tệp tải lên hay tệp của bên thứ ba nào, thay vì gỡ lỗi sau này.

Có — và nó tạo ra lỗi phân tích khó hiểu nhất trong mọi lỗi phân tích, vì tệp trông hoàn toàn ổn.

Những gì bạn thấy

SyntaxError: Unexpected token  in JSON at position 0
Unexpected character '\uFEFF'

Ký tự trong thông báo đó là vô hình. Vị trí 0 nghĩa là byte đầu tiên.

cat không cho thấy gì bất thường. hexdump -C file.json | head -1 thì có:

00000000  ef bb bf 7b 0a 20 20 22  61 22 3a 20 31 0a 7d 0a  |...{  "a": 1.}.|

7b là {. Ba byte trước nó là BOM.

BOM đến từ đâu

Byte order mark ra đời cho UTF-16, nơi thứ tự byte thực sự thay đổi. UTF-8 chỉ có một thứ tự byte, nên BOM là chi phí thuần túy — vậy mà Notepad trên Windows, một số bản xuất Excel và vài IDE cũ vẫn ghi nó theo mặc định.

RFC 8259 rất rõ ràng: JSON trao đổi giữa các hệ thống phải là UTF-8, và các hiện thực không được thêm BOM. Trình phân tích có thể bỏ qua BOM ở đầu nhưng không bắt buộc. Trình duyệt và Node chọn không bỏ qua.

Ba cách loại bỏ nó

Lưu không có BOM. Trong VS Code, bấm vào encoding ở thanh trạng thái và chọn "Save with Encoding → UTF-8", không chọn "UTF-8 with BOM".

Loại bỏ từ shell.

sed -i '1s/^\xEF\xBB\xBF//' data.json

Loại bỏ khi đọc. Đây là cách sửa bền vững cho mọi thứ nhận tệp tải lên hoặc tệp của bên thứ ba:

const text = require('node:fs').readFileSync('data.json', 'utf8').replace(/^\uFEFF/, '');
JSON.parse(text);

Trong Python, open(path, encoding='utf-8-sig') xử lý việc này tự động.

Hai vấn đề trông giống hệt

  • Dấu cách độ rộng bằng không (U+200B) — xuất hiện khi sao chép JSON từ trang web; triệu chứng giống hệt, nhưng mã điểm khác.
  • Nháy toàn độ rộng — bộ gõ tiếng Trung biến "key" thành “key”, trông gần như giống hệt nhưng thất bại với Unexpected token “.

Cả ba đều là lỗi ký tự vô hình. Cách chẩn đoán luôn giống nhau: đổ các byte đầu ra dạng hex thay vì nhìn chằm chằm vào văn bản.

Hỏi đáp

Làm sao biết một tệp có bắt đầu bằng BOM không?

cat không cho thấy gì, nên hãy chạy hexdump -C file.json | head -1. Nếu kết quả bắt đầu bằng ef bb bf, tệp có BOM; trong một tệp UTF-8 sạch, 7b (tức {) phải đứng đầu.

Tại sao lỗi luôn chỉ vào dòng 1, cột 1?

BOM nằm trước mọi thứ khác, nên ký tự đầu tiên trình phân tích đọc là U+FEFF. Vì thế thất bại rơi vào đầu tệp, làm tệp trông như rỗng.

Có nên loại bỏ BOM trước khi phân tích không?

Có. Khi máy chủ đọc cấu hình hoặc phân tích tệp tải lên, hãy loại bỏ U+FEFF ở đầu trước — replace(/^\uFEFF/, '') trong Node, encoding='utf-8-sig' trong Python — rẻ hơn nhiều so với chẩn đoán về sau.

Đọc thêm