Command Palette

Search for a command to run...

為什麼我的 JSON 無效?常見錯誤和修復

為什麼我的 JSON 無效?常見錯誤和修復

T
Toolz Team
|Sep 13, 2026|16 閱讀
在 Google 上首選 Toolz。dev

數據工具 系列的一部分

JSON 驗證器

根據 RFC 8259 驗證 JSON,並取得第一個語法錯誤的精確行、列和字符,以及重複金鑰偵測和結構統計資料。客戶端,無註冊。

使用JSON 驗證器

我建造 工具。dev在此之前,我花了數年時間運送 WordPress 外掛程式和 Laravel API。在所有這些中,我浪費最多時間的單一錯誤訊息是 &quot 的一些變體; JSON 中位置 428 處有意外的令牌。它幾乎什麼也沒告訴你。沒有行,沒有列,它命名的位置通常比錯誤的位置多幾個字元。你最終會用手計算一個縮小斑點中的字符,或者將整個有效負載粘貼到編輯器中並瞇著眼睛。我建造了 JSON 驗證器 所以我再也不用這樣做了,這就是它的作用以及為什麼驗證 JSON 比看起來更棘手的指南。

TL;DR: JSON 驗證器根據 RFC 8259 中的語法檢查文本,當文本被破壞時,它會告訴您第一個錯誤的確切行、列和字符,並按照其預期進行表述。它還捕獲普通解析器隱藏的內容:重複的鍵,這些鍵會靜默地折疊到最後一個值,並報告有效文件的結構(物件、數組和鍵數、嵌套深度和位元組大小)。它不是格式化程式。格式化程式假設輸入已經有效;驗證器是您準確達到的目標,但實際上它不是。

JSON 有效意味著什麼?

JSON 是一種語法嚴格的小格式。目前的標準是 RFC 8259,這與 ECMA-404,它們之間準確地定義了有效文件可能包含的內容。 JSON 文字是單一值。該值是一個物件、一個數組、一個字串、一個數字 true, false,或者 null。 物體用大括號包裹並保持逗號分隔 "key": value 成對的。數組包裹在括號中並保存逗號分隔的值。字串用雙引號包裹,絕不用單引號包裹。數字遵循特定的形狀,沒有前導零,也沒有尾隨小數點。沒有註釋,也沒有尾隨逗號。

最後一句話是大多數現實世界 JSON 出錯的地方,因為很多 JSON 人手寫並不是真正的 JSON。它是一個設定檔 // 評論,或從 JavaScript 原始碼複製的對象,其中單引號和尾隨逗號很好,或者手工編輯的固定裝置,其中有人添加了一個字段並留下了一個懸空逗號。所有這些都被嚴格的解析器和驗證器拒絕'他的工作是在特定位置拒絕它們,而不是聳聳肩。

值得澄清的一點是,因為它讓多年前學習 JSON 的人感到困擾:裸值是一個完整、有效的 JSON 文件。 42 JSON 本身就是有效的。也是如此 "hello",也是如此 true. 老的 RFC 4627 要求頂層是物件或數組,但該限制在 2014 年被取消,當時 RFC 7159(後來的 8259)取代了它。如果工具告訴您 42 JSON 不有效,該工具遵循的規範已經過時了十多年。

為什麼 JSON。parse 錯誤報告程式如此糟糕?

專用驗證器獲得其地位的原因是,內建於您的語言中的解析器是針對快樂路徑進行最佳化的,而不是為了解釋悲傷路徑。 JSON.parse 在瀏覽器中拋出 a SyntaxError 其訊息是特定於引擎的,通常會為您提供沒有行或列的字元偏移量。 V8 表示 " JSON 中位置 148 處的意外令牌}。火狐說&引用; JSON。parse:第 1 行第 149 欄的意外字元。 Safari 又說了一些不同的話。他們都沒有告訴你他們的期望,位置是從字串的開頭開始測量的,當你的 JSON 有幾行以上的那一刻,位置就毫無用處。

toolz。dev 上的驗證器不使用 JSON.parse. 它使用手寫的遞歸下降解析器在文字本身上行走,邊走邊追蹤行和列,因此當它停止時,它可以把所有三個座標交給您:行、列和絕對字元偏移量。更重要的是,它知道它位於中間的語法規則,因此訊息是特定的。代替 "意想不到的令牌,"你得到 "在閉括號之前不允許使用尾引逗號,"或&引用;物件鍵必須是雙引字串,"或&引用;期望物件成員後面有一個逗號或一個閉括號。&引用;這個差異就是五秒鐘內修復檔案和尋找檔案之間的差異。

它還在違規行上的確切字元下繪製了一個插入符號,就像編譯器所做的那樣。當您查看設定檔的第 34 行時,"第 12 欄"沒關係,但是 ^ 直接坐在雜散報價下面速度更快。

驗證器按名稱捕獲哪些 JSON 錯誤?

這些是我最常看到的失敗,無論是在我自己的工作中還是在此類工具的支援執行緒中。驗證器命名每個驗證器,而不是報告通用令牌錯誤。

錯誤 它看起來像什麼 為什麼無效
尾隨逗號 {"a": 1,} 或者 [1, 2,] JSON 沒有尾隨逗號;標準's 語法根本不允許在結束大括號或括號之前使用
單引號 {'name': 'Liton'} 字串和鍵必須使用雙引號;單引號是 JavaScript 的習慣,而不是 JSON
缺少逗號 {"a": 1 "b": 2} 第一個成員之後的每個成員前面都必須有一個逗號
評論 {"a": 1} // note JSON 沒有註解語法;這 // 之後的一切都是意想不到的內容
未引用的密鑰 {name: "Liton"} 與 JavaScript 物件文字不同,鍵是字串並且必須引用
前導零 {"n": 007} 數字可能沒有前導零,因此 007 無效;寫 7
尾隨小數點 {"n": 5.} 小數點後的分數至少需要一位數字
原始控製字元 字串內的文字選項卡或換行符 字串內的控製字元必須轉義為 \t, \n,等等
NaN 或無限 {"n": NaN} 這些在 JavaScript 中有效,但不是 JSON 值
未終止的字串 {"a": "oops} 沒有結束引號的字串運行到輸入的末尾

其中每一個都會產生一個簡單的語言訊息和一個位置。前導零情況是專門建構的解析器為何有幫助的一個很好的例子:通用解析器讀取 007 作為數字 0 然後就絆倒了 7 作為&引用;額外內容,&引用;指著你 7,當真正的問題是它前面的兩個零時。驗證器首先檢查前導零模式並直接告訴您。

重複的密鑰怎麼樣?

這是在生產中比任何語法錯誤更讓我煩惱的一個,因為它根本不是語法錯誤。這是有效的 JSON:

{
  "timeout": 30,
  "retries": 3,
  "timeout": 60
}

RFC 8259 說明物件中的名稱 "應該是唯一的,"但它並不禁止重複,因此解析器需要接受這一點。接下來發生的情況是問題開始的地方:標準說重複名稱的行為是不可預測的,實際上幾乎每個解析器都保留最後一個值並默默地丟棄較早的值。所以這個物件解析為 {"timeout": 60, "retries": 3},並且 "timeout": 30 您小心地設定在文件頂部,沒有任何警告。如果兩個人編輯了配置,或者合併出了問題,或者模板步驟兩次發出相同的密鑰,則您會遇到一個錯誤,任何解析器都不會為您標記。

驗證器標記它。預設情況下,重複金鑰檢測處於開啟狀態,並且由於重複項是合法的,因此它被報告為警告而不是錯誤:該文件仍然有效,但您會被告知在同一物件中多次出現的每個金鑰,其行和a JSON 指針 路徑,這樣你就可以在嵌套結構中找到它。如果您真的想要重複項,您可以關閉檢查。大多數時候,看到警告就是您意識到出了什麼問題的那一刻。

驗證器與格式化程式有何不同?

人們可以互換使用這些詞,工具重疊,但他們回答不同的問題。 A JSON 格式化程式 採用您已經相信有效的 JSON,並以一致的縮排重新列印它,以便人類可以閱讀它。如果您遞給格式化程式損壞的 JSON,它能做的最好的事情就是拒絕。驗證器'整個目的是損壞的案例:它告訴您在哪裡以及為什麼。 toolz。dev 驗證器執行這兩個工作,因為一旦確認文件有效,它就已經解析了它,因此它可以在同一遍中漂亮地列印結果。但標題特徵是診斷,而不是縮排。

與相鄰工具也有同樣的關係。這 JSON 小型化器 剝離空白以縮小有效負載,這僅在有效輸入時才有意義。這 JSON 分類器 再次根據有效輸入重新排序穩定差異的鍵。這 JSON 逃脫和逃脫 該工具處理將 JSON 嵌入字串中。和 JSONPath 測試儀 查詢您已確認的文檔格式良好。驗證是所有這些步驟之前的步驟,這就是為什麼每當 API 回應或設定檔表現奇怪時,我都會先執行該步驟。關於它們如何組合在一起,有更廣泛的了解 JSON 工具終極指南.

結構統計告訴你什麼?

當文件驗證時,該工具會報告其形狀:它包含多少個物件和數組、多少個鍵、多少個字串、數字、布林值和空值、它嵌套的深度以及它在字元和UTF-8 位元組中的大小。這不是裝飾。當您收到不熟悉的 API 回應時,深度數字會一目了然地告訴您是否正在處理平面記錄或深度嵌套的樹,而密鑰計數會告訴您解析它的工作量大致是多少。

位元組數字比人們想像的要重要。請求大小限制、訊息佇列限制和資料庫列限制幾乎總是以位元組而不是字元來衡量,當 JSON 包含 ASCII 以外的任何內容時,兩者就會有所不同。表情符號或重音名稱是螢幕上的一個字符,但線上有兩個、三個或四個位元組。如果有效負載遇到 256 KB 限制,字元數會誤導您,而位元組數不會誤導您。驗證器計算真實的 UTF-8 位元組長度,因此您看到的數字就是限制正在計數的數字。

我如何使用它

我的工作流程無聊又快,這就是重點。當整合中斷時,我會將原始回應正文直接從網路標籤複製出來並將其貼上到驗證器中。如果它有效,綠色結果和統計數據告訴我問題出在其他地方,在我的程式碼中而不是他們的數據中,並且我在兩秒鐘內排除了一整類原因。如果它無效,我會得到行和列,修復它,然後繼續。當我手動編輯設定檔時,我會在提交之前將其貼上,主要是為了捕捉我似乎總是留下的尾隨逗號以及複製貼上中偶爾出現的重複密鑰。對於任何組裝自己的套件的人來說,驗證器與其中的其他必需品並排 web 開發人員工具包.

隱私角度也不是事後的想法。最需要驗證的 JSON 人正是他們應該最小心處理的 JSON:攜帶令牌的 API 回應、帶有憑證的設定檔、帶有客戶資料的有效負載。驗證器所做的一切都發生在您的瀏覽器、JavaScript 和電腦上。沒有任何內容被上傳、記錄或儲存。您可以在驗證時開啟網路選項卡,或斷開網路連線並查看工具繼續工作來證明這一點。

常見問題

為什麼我的 JSON 說它看起來不錯就無效?

最常見的原因是結束大括號或括號之前的尾隨逗號、JSON 需要雙引號的單引號、兩個成員之間缺少逗號或評論(JSON 根本不允許)。這四個都很容易被眼睛錯過,尤其是在一個大文件中。驗證器會命名它找到的驗證器,並為您提供準確的行和列,因此您無需掃描整個文檔,而是直接跳到它停止的字元。

單一數字或字串本身是否有效 JSON?

是的。根據 RFC 8259,任何 JSON 值都是完整的 JSON 文本,因此 42, "hello", true, 和 null 全部自行驗證。頂層必須是物件或數組的規則來自較舊的 RFC 4627,並於 2014 年被刪除。拒絕裸值的工具遵循過時的規範。

驗證器會更改或上傳我的資料嗎?

不,它會解析瀏覽器中的文本,並且永遠不會將其發送到任何地方。為了方便起見,它會在有效文件上產生列印精美的副本,但該副本是在本地生成的,並且原始副本永遠不會傳輸、記錄或儲存。由於沒有伺服器往返,因此該工具也可以在頁面載入後斷開網路的情況下運作。

如果 JSON 仍然有效,為什麼我應該關心重複的金鑰?

因為重複幾乎總是意味著您無意的資料遺失。該標準允許重複的金鑰,但未定義其處理,並且在實踐中解析器僅保留最後一個值並刪除其餘值。所以配置在哪裡 timeout 出現兩次悄悄失去第一個設定。驗證器會警告您每個重複的鍵及其位置,這通常是您發現錯誤合併或複製貼上錯誤的時刻。

這可以透過註釋(例如 tsconfig 或 VS Code 設定檔)來驗證 JSON 嗎?

不,這是故意的。這些文件是帶有評論的 JSON (JSONC) 或 JSON5,它們是放寬規則的單獨格式。驗證器針對嚴格的 RFC 8259,因此它將評論標記為錯誤。如果您需要設定檔中的註解,即訊號,則格式應該是為其建置的,例如 YAML 或 TOML,而不是超出標準允許的 JSON。

驗證 JSON 和格式化 JSON 有什麼不同?

驗證會檢查文字是否遵守 JSON 語法,如果沒有,則會告訴您它到底在哪裡中斷。格式化假設文字已經有效,並且僅調整其空格以提高可讀性。當出現問題時,您會聯絡驗證器,並且需要知道什麼;當一切都很好並且您只是希望它可讀時,您就聯絡格式化程式。這個工具可以兩者兼而有之,但它存在的理由是診斷。

我可以驗證多大的文件?

舒適地達到數十兆字節,僅受瀏覽器限制'記憶體,因為整個文件是在您的裝置上一次解析的。沒有上傳大小上限,因為沒有上傳。對於真正巨大的文件,在千兆位元組中,串流命令列驗證器是更好的工具,因為瀏覽器會立即將整個文字保存在記憶體中。

Comments

0 comments

0/2000 characters

No comments yet. Be the first to share your thoughts!