Công cụ dành cho nhà phát triển · JSON trình định dạng và xác thực
Ký tự vô hình phá vỡ JSON: BOM, dấu ngoặc kép thông minh và NBSP
· Cách thức hoạt động
json developer-workflow xác nhận
Khi trình xác thực báo cáo lỗi ở ký tự đầu tiên và tệp trông hoàn hảo thì nguyên nhân thường là do ký tự vô hình. Bài đăng này giải thích các dấu thứ tự byte, dấu ngoặc kép kiểu chữ và dấu cách không ngắt cũng như cách báo cáo từng dấu cách.
Dòng 1, cột 1, không thấy có gì sai cả
Dòng 1, cột 1, không có gì sai cả — tài liệu JSON có thể bắt đầu bằng một ký tự chiếm vị trí thực nhưng hiển thị không có hình tượng rõ ràng. Dấu ngoặc nhọn mở sau đó xuất hiện ở vị trí đầu tiên mặc dù có dấu thứ tự byte hoặc ký tự có độ rộng bằng 0 đứng trước nó. Trình phân tích cú pháp nghiêm ngặt sẽ gặp điểm mã ẩn đó trước khi nó đạt đến `{`, do đó việc báo cáo cột đầu tiên là chính xác chứ không mơ hồ. Màn hình và trình tự ký tự chỉ kể những câu chuyện khác nhau.
Đừng xóa dấu ngoặc nhọn trông có vẻ chính xác chỉ vì dấu mũ xuất hiện bên cạnh nó. Kiểm tra điểm mã ở phần bù được báo cáo, bật khoảng trắng hiển thị hoặc chuyển sang chế độ xem thập lục phân. ToolAcre không âm thầm xóa BOM ở đầu trước khi phân tích cú pháp và trình quét của nó sẽ báo cáo ký tự không mong muốn đầu tiên.
Dấu thứ tự byte UTF-8
các UTF-8 dấu thứ tự byte - chuỗi byte EF BB BF giải mã thành U+FEFF ở đầu một tệp. Thứ tự byte không mơ hồ trong UTF-8, vì vậy dấu này là không cần thiết nhưng một số trình soạn thảo và công cụ xuất vẫn thêm nó làm chữ ký mã hóa. RFC 8259 nói JSON máy phát điện không được thêm một BOM để nối mạng JSON, mặc dù các trình phân tích cú pháp có thể chọn bỏ qua một cái để đảm bảo khả năng tương tác. Dung sai đó không thể được giả định trên các công cụ.
Trong chuỗi JavaScript, BOM là một ký tự mặc dù biểu diễn UTF-8 của nó sử dụng ba byte. ToolAcre báo cáo vị trí trong các ký tự chuỗi, do đó dấu đầu xuất hiện ở dòng 1, cột 1. Định cấu hình trình chỉnh sửa để lưu UTF-8 mà không có BOM hoặc xóa U+FEFF trước khi phân phối tệp.
Trích dẫn thông minh từ trình xử lý văn bản
Các trích dẫn thông minh từ trình xử lý văn bản — dấu mở và đóng kiểu chữ trông bóng bẩy trong văn xuôi nhưng JSON chỉ nhận ra ASCII dấu ngoặc kép U+0022 làm dấu phân cách chuỗi. U+201C và U+201D là các ký tự Unicode thông thường. Bên ngoài một chuỗi, chúng không thể bắt đầu tên hoặc giá trị thuộc tính, vì vậy trình xác thực sẽ báo cáo chính trích dẫn thông minh. Tính năng tự động sửa trong trò chuyện, email hoặc trình chỉnh sửa tài liệu thường đưa ra thay đổi sau khi JSON ban đầu hợp lệ.
Thay thế dấu phân cách bằng dấu ngoặc kép thẳng, sau đó kiểm tra dấu nháy đơn và dấu ngoặc kép thuộc về giá trị. Dấu ngoặc kép là hoàn toàn hợp pháp vì nội dung bên trong chuỗi JSON được phân tách chính xác, chẳng hạn như `"She said “go”"`; chúng chỉ thất bại khi được yêu cầu thực hiện công việc ngữ pháp của dấu phân cách.
Khoảng trắng không ngắt và ký tự có độ rộng bằng 0
Khoảng trắng không ngắt và ký tự có độ rộng bằng 0 — khoảng trắng JSON là một danh sách ngắn có chủ ý: khoảng trắng thông thường U+0020, tab U+0009, nguồn cấp dữ liệu dòng U+000A và trả về đầu dòng U+000D. Khoảng trắng không ngắt U+00A0 có thể trông giống với khoảng trắng bình thường giữa dấu hai chấm và giá trị, nhưng nó không có trong danh sách đó. Khoảng trắng có độ rộng bằng 0 U+200B không hiển thị gì cả, tuy nhiên nó vẫn là một ký tự không mong đợi bên ngoài chuỗi được trích dẫn.
Các trang web sử dụng khoảng trắng không ngắt để giữ các từ lại với nhau và hệ thống nhắn tin có thể chèn các ký tự có độ rộng bằng 0 để gói hoặc xử lý tập lệnh. Việc sao chép các đoạn mã được định dạng có thể đưa chúng vào cấu hình. Thay thế các ký tự cấu trúc NBSP bằng khoảng trắng thông thường và xóa các ký tự có độ rộng bằng 0 ngoài ý muốn, được hướng dẫn bởi phần bù được báo cáo.
Ví dụ hoạt động: cấu hình được sao chép từ tin nhắn trò chuyện
Ví dụ đã hoạt động: một cấu hình được sao chép từ tin nhắn trò chuyện — giả sử văn bản hiển thị giống `{"mode": "safe"}` nhưng việc xác thực không thành công ngay từ đầu. Chế độ xem hex hiển thị EF BB BF trước dấu ngoặc nhọn. Việc xóa BOM đó sẽ đưa báo cáo tiếp theo vào báo giá trước `mode`, thực tế là U+201C. Thay thế cả hai dấu phân cách thông minh bằng U+0022 sau đó hiển thị U+00A0 giữa dấu hai chấm và giá trị.
Thay đổi không gian không phá vỡ cấu trúc đó thành U+0020 và xác thực một lần nữa. Kết quả được chấp nhận bây giờ có thể được định dạng bình thường. Trình tự này cho thấy lý do tại sao việc chỉ sửa chữa những gì màn hình hiển thị là không đáng tin cậy: một số ký tự vô hình hoặc trông giống nhau có thể chiếm các vị trí ngữ pháp khác nhau. Theo dõi từng dòng và cột, xác định điểm mã thực tế, thực hiện một sự thay thế có chủ ý và chạy lại xác thực.
Làm thế nào để nhìn thấy cái vô hình
Cách xem phần vô hình - bật tùy chọn hiển thị khoảng trắng của trình chỉnh sửa để phân biệt các tab với khoảng trắng và hiển thị các khoảng trống bất thường, sau đó sử dụng trình kiểm tra Unicode hoặc chế độ xem hex cho các ký tự trông vẫn giống hệt nhau. UTF-8 BOM xuất hiện dưới dạng EF BB BF, khoảng trắng không ngắt là C2 A0 và khoảng trắng có độ rộng bằng 0 là E2 80 8B. Dấu ngoặc kép mở và đóng thông minh xuất hiện dưới dạng E2 80 9C và E2 80 9D.
Khớp hệ tọa độ của chẩn đoán trước khi đếm. ToolAcre quét chuỗi JavaScript, do đó các cột của nó đếm UTF-16 đơn vị mã thay vì UTF-8 byte. Do đó, trình soạn thảo hex định hướng byte có thể hiển thị phần bù số lớn hơn sau các ký tự không phải ASCII. Sử dụng dòng được báo cáo để thu hẹp tìm kiếm, kiểm tra các điểm mã lân cận và chỉ dịch khi cần.
Điều này không bao gồm những gì
Điều này không bao gồm những gì - mojibake chẳng hạn như `café` có thể hoàn toàn hợp lệ JSON. Trình phân tích cú pháp nhìn thấy một chuỗi ký tự chuỗi thông thường và không có bằng chứng nào cho thấy UTF-8 byte trước đó đã được giải mã dưới dạng mã hóa khác. Tương tự, dấu cách không ngắt hoặc ký tự có độ rộng bằng 0 bên trong giá trị được trích dẫn là hợp lệ về mặt cú pháp. Xác thực sẽ phát hiện các ký tự vi phạm ngữ pháp JSON; nó không thể quyết định liệu nội dung Unicode hợp lệ có phù hợp với ý định của tác giả hay không.
Sửa chữa lỗi mã hóa ở ranh giới nơi byte trở thành văn bản, sử dụng kiến thức về mã hóa gốc và mã hóa sai. Không mã hóa và giải mã chuỗi JSON nhiều lần cho đến khi nó trông đẹp hơn vì điều đó có thể làm hỏng các ký tự vốn đã chính xác. Chuẩn hóa cấp ứng dụng cũng là một quyết định riêng biệt: các chuỗi Unicode giống hệt nhau về mặt hình ảnh có thể so sánh khác nhau trong khi vẫn hợp lệ.
Takeaway: tin tưởng vào cột được báo cáo ngay cả khi dòng trông rõ ràng
Bài học rút ra: hãy tin cậy cột được báo cáo ngay cả khi dòng trông rõ ràng — các ký tự ẩn và dấu câu trông giống nhau vẫn chiếm vị trí chính xác trong nguồn. BOM ở đầu, dấu phân cách cong, dấu cách không ngắt hoặc dấu có độ rộng bằng 0 có thể ngăn trình phân tích cú pháp tiếp cận dấu ngoặc nhọn hoặc trích dẫn có vẻ chính xác. Hiển thị khoảng trắng, kiểm tra các điểm mã hoặc byte và thay thế ký tự có danh tính xung đột với vai trò ngữ pháp của nó thay vì chỉnh sửa ngẫu nhiên JSON hiển thị gần đó.
Hãy nhớ rằng các vị trí có thể đếm các ký tự trong khi công cụ hex đếm các byte được mã hóa, vì vậy hãy so sánh văn bản xung quanh thay vì mong đợi mọi số bù đều khớp. Chỉ xóa BOM ở ranh giới tài liệu, chuyển đổi dấu phân cách thông minh thành U+0022 và thay thế khoảng cách cấu trúc không hợp lệ mà không xóa chuỗi Unicode hợp pháp bên trong.