繁體中文

開發者工具 · JSON 格式化程式和驗證程序

JSON 驗證器如何找到錯誤的確切行和列

· 工作原理

json 驗證 開發人員工作流程

位於小型 JSON 文件中意外鍵下的插入符號
原始 ToolAcre 向量圖

瀏覽器引擎報告 JSON.parse 失敗的方式不同,有些只提供字元偏移量。這篇文章解釋了驗證器如何將其轉換為行和列,以及為什麼位置標記解析停止的位置而不是出錯的位置。

錯誤訊息什麼也沒告訴你-為什麼「Unexpected token in JSON atposition 1432」在 400 行檔案中毫無用處

在長配置中,諸如“意外令牌”之類的錯誤會令人沮喪,因為它沒有提供可以在編輯器中打開的位置。 JSON.parse 是瀏覽器的權威解析器,但其診斷文字會因 JavaScript 引擎和版本而異。 ToolAcre 不會透過匹配不穩定的英文錯誤字串來猜測位置。如果 JSON.parse 失敗,則單獨的嚴格掃描器會遍歷原始文字以識別 JSON 語法無法接受的第一個字元。

JSON 解析器在讀取時實際執行的操作 — 演練標記化和一次消耗一個值的遞歸下降語法

JSON 具有六個結構字元(大括號、方括號、冒號和逗號)以及可以是字串、數字、陣列、物件、true、false 或 null 的值。在將逗號稱為分隔符號之前,掃描器需要知道它是否位於引號的字串內:{"note":"A,B"} 有一個值,而不是兩個值。它遍歷一個值或一個物件成員,並檢查接下來可以合法遵循的內容。 RFC 8259 定義了此語法,與 JavaScript 物件文字不同,它不允許註解或尾隨逗號。

從字元偏移量到行和列 - 計算換行符直到失敗偏移量,以及為什麼 CRLF 結尾和多位元組字元使計數變得複雜

掃描器通常從原始 JavaScript 字串中從零開始的偏移量開始。為了使其有用,請計算偏移量之前的換行符,並找出故障與上次換行符的距離。 CRLF 應被視為一條視線結束線,而不是兩條線; JavaScript 字串中的位置計算 UTF-16 代碼單元,而不是磁碟上的 UTF-8 bytes。非 BMP 表情符號可以在編輯器中佔用兩個代碼單元,直觀地顯示一個字形。 UI 報告行、列和摘錄,以便您可以根據貼上的文件檢查插入符號。

解析停止的地方並不是錯誤所在的地方 - 在下一個鍵處報告缺少逗號,並且雜散的引號可以將錯誤推到很多行

第一個不可能的標記通常是在最初的錯誤之後。在物件中,忘記 true 後面的逗號會使下一個屬性開頭的引號非法:解析器需要逗號或右大括號。未終止的字串可能會導致錯誤出現在稍後的換行符或輸入末尾。從報告的點向後讀取以找到丟失的分隔符號;不要假設必須刪除插入符號下的字元。

工作範例:缺少一個逗號的配置 - 報告的位置、周圍的標記以及如何向後走到真正的原因

嘗試使用文字三行文件 {"name":"demo",後面跟著第二行的 "enabled":true 和第三行的 "port":8080},true 後面沒有逗號。 ToolAcre 報告第 3 行,第 1 列,偏移量 31:它期望在前面的屬性後面有一個逗號或 },並且在「port」的第一個引號下顯示一個插入符號。在第二行末尾插入逗號,然後再次驗證。這是對第一個語法障礙的診斷,而不是對「連接埠」一詞錯誤的判斷。

瀏覽器引擎有何不同 - V8、SpiderMonkey 和 JavaScriptCore 對相同故障的表述方式不同,這就是為什麼一致的行和列報告會有所幫助

對於相同的 JSON.parse 失敗,V8、SpiderMonkey 和 JavaScriptCore 使用了不同的措辭,有時也使用了不同的上下文片段。當本機解析器拒絕該值時,ToolAcre 的掃描器會提供自己的結構原因和位置。如果掃描器不同意 JSON.parse,則該工具將傳回引擎錯誤而不是偽造位置。這種後備措施比自信地指向猜測的角色更安全。

這不包括語義問題,例如錯誤類型、缺失欄位或架構違規,語法驗證器永遠不會標記這些問題

對於您的應用程式來說,語法上有效的物件仍然可能是錯誤的:缺少必填欄位、以文字形式寫入的年齡、兩個重複的鍵或對不存在檔案的引用不會自動成為無效 JSON。 RFC 8259 規定成員名稱應該是唯一的以實現互通性,但僅僅解析並不會強制執行您的 API 架構。在此驗證語法並驗證使用文件的程式中的語義約束​​。

重點:將位置讀取為「語法無法接受的第一個標記」—以及 JSON 格式化程式和驗證程式如何在不上傳文字的情況下報告該行和列

將報告的位置視為「該語法無法接受的第一個標記」。向後追溯原因,解決一個問題並重新運行。 JSON 格式化程式和驗證程式在本機執行此操作,無需上傳貼上的設定。如果離線編輯器可以診斷該文件,請勿將真實的生產憑證貼到任何公共網站中。