開發者工具 · JSON 格式化程式和驗證程序
破壞 JSON 的不可見字元:BOM、智慧引號和 NBSP
· 工作原理
json 開發人員工作流程 驗證
當驗證器在第一個字元處報告錯誤並檔案看起來很完美時,通常會歸咎於不可見的字元。這篇文章解釋了位元組順序標記、印刷引號和不間斷空格,以及如何報告每一項。
行 1,欄位 1,沒有看到任何錯誤
行 1,列 1,沒有什麼問題 — JSON 檔案可以以佔據實際位置但渲染時沒有可見字形的字元開頭。然後,左大括號出現在第一個,即使其前面有一個位元組順序標記或零寬度字元。嚴格的解析器在到達 `{` 之前會遇到該隱藏程式碼點,因此報告第一列是準確的而不是模糊的。顯示和字元序列只是講述不同的故事。
不要僅僅因為插入符號出現在它旁邊而刪除看起來正確的大括號。檢查報表偏移處的程式碼點,啟用可見空白或切換到十六進位視圖。 ToolAcre 在解析之前不會默默地刪除前導 BOM,其掃描器會報告第一個意外字元。
UTF-8 位元組順序標記
UTF-8 位元組順序標記 — 位元組序列 EF BB BF 在檔案開頭解碼為 U+FEFF。 UTF-8 中的位元組順序並不含糊,因此該標記是不必要的,但某些編輯器和匯出工具仍然將其新增為編碼簽章。 RFC 8259 表示 JSON 產生器不得將 BOM 加入到網路 JSON 中,儘管解析器可能會選擇忽略一個 BOM 以實現互通性。不能跨工具假設這種容忍度。
在 JavaScript 字串中,BOM 是一個字符,即使其 UTF-8 表示形式使用三個位元組。 ToolAcre 報告字串字元中的位置,因此前導標記出現在行 1、欄位 1 處。配置編輯器以在分發檔案之前儲存不含 BOM 的 UTF-8 或刪除 U+FEFF。
來自文字處理器的智慧引用
來自文字處理程式的智慧引號 — 印刷的開始和結束標記在散文中看起來很優美,但 JSON 只將 ASCII 引號 U+0022 識別為字串分隔符號。 U+201C 和 U+201D 是普通的 Unicode 字元。在字串之外,它們不能以屬性名稱或值開頭,因此驗證器會報告智慧引號本身。聊天、電子郵件或檔案編輯器中的自動更正通常會在 JSON 最初有效後引入變更。
將分隔符號替換為直雙引號,然後檢查屬於該值的撇號和引號。作為正確分隔的 JSON 字串內的內容,大引號是完全合法的,例如 `"She said “go”"`;僅當要求執行分隔符的語法工作時,它們才會失敗。
不間斷空格和零寬度字符
不間斷空格和零寬度字元 — JSON 空白是一個故意簡短的清單:普通空格 U+0020、製表符 U+0009、換行符 U+000A 和回車符 U+000D。不間斷空格 U+00A0 看起來可能與冒號和值之間的普通空格相同,但它不在該清單中。零寬度空格 U+200B 完全不顯示任何內容,但它仍然是帶引號的字串之外的意外字元。
網頁使用不間斷空格將單字保持在一起,訊息傳遞系統可能會插入零寬度字元以進行換行或腳本處理。複製格式化的片段可以將它們帶入配置中。根據報告的偏移量,用普通空格替換結構 NBSP 字元並刪除不需要的零寬度字元。
工作範例:從聊天訊息複製的配置
工作範例:從聊天訊息複製的設定 - 假設可見文字類似於 `{"mode": "safe"}`,但驗證在開始時失敗。六角視圖顯示支架前的 EF BB BF。刪除該 BOM 會將下一個報告推進到 `mode` 之前的報價,實際上是 U+201C。將兩個智慧分隔符號替換為 U+0022 然後在冒號和值之間公開 U+00A0。
將該結構不間斷空格變更為 U+0020 並再次驗證。現在可以正常格式化接受的結果。這個序列說明了為什麼僅修復螢幕顯示的內容是不可靠的:幾個不可見或相似的字元可能佔據不同的語法位置。按照每一行和每一列,識別實際的程式碼點,進行有意的替換並重新執行驗證。
如何看到看不見的東西
如何查看不可見的內容 — 啟用編輯器的渲染空白選項來區分製表符和空格並顯示不尋常的間隙,然後使用 Unicode 檢查器或十六進位視圖查看看起來仍然相同的字元。 UTF-8 BOM 顯示為 EF BB BF,不間斷空格顯示為 C2 A0,零寬度空格顯示為 E2 80 8B。智慧開盤價和收盤價顯示為 E2 80 9C 和 E2 80 9D。
在計數之前匹配診斷的座標系。 ToolAcre 掃描 JavaScript 字串,因此其欄位計數 UTF-16 程式碼單元,而不是 UTF-8 位元組。因此,面向位元組的十六進位編輯器可以在非 ASCII 字元之後顯示更大的數字偏移量。使用報告的行縮小搜尋範圍,檢查相鄰的代碼點並僅根據需要進行翻譯。
這不包括什麼
這不包含什麼 - mojibake 例如 `café` 可以是完全有效的 JSON。解析器看到普通的字串字元序列,並沒有證據表明 UTF-8 位元組之前已解碼為另一種編碼。同樣,帶引號的值內不間斷的空格或零寬度字元在語法上也是有效的。驗證擷取違反 JSON 語法的字元;它無法決定有效的 Unicode 內容是否符合作者的意圖。
使用原始編碼和錯誤編碼的知識修復位元組變為文字邊界處的編碼損壞。不要重複編碼和解碼 JSON 字串,直到它看起來更好,因為這可能會損壞已經正確的字元。應用程式層級規範化也是一個單獨的決定:視覺上相同的 Unicode 序列可能會進行不同的比較,但仍保持有效。
重點:即使線路看起來很乾淨,也要相信報告的列
重點:即使行看起來很乾淨,也要相信報告的列 - 不可見的字元和看起來相似的標點符號仍然佔據來源中的精確位置。前導 BOM、捲曲分隔符號、不間斷空格或零寬度標記可以阻止解析器到達顯示正確的大括號或引號。顯示空白,檢查代碼點或位元組並替換其身份與其語法角色衝突的字符,而不是隨機編輯附近可見的 JSON 。
請記住,位置可能會計算字符,而十六進制工具會計算編碼字節,因此請比較周圍的文字,而不是期望每個偏移量都匹配。僅刪除檔案邊界處的 BOM,將智慧分隔符號轉換為 U+0022 並取代無效的結構間距,而不刪除字串內的合法 Unicode。