ZonoTools

常見的 JSON 到 YAML 轉換錯誤以及如何修復它們

By ZonoTools11 min read

縮排錯誤

YAML 結構由空格定義,而不是大括號。 JSON 準確地告訴您物件以}結尾的位置; YAML 期望每個巢狀鍵都在其父級下縮排一個一致的步驟(在工俱生態系統中幾乎總是兩個空格)。當您 將 JSON 轉換為 YAML 時,草率的格式化程式(或手動編輯)可能會將子項向左移動一列,使其成為您所認為的父項的 同級

將此 JSON 轉換為 YAML 的圖片:

如果portserver對齊而不是嵌套在其下,則解析器會將port視為 頂級鍵,而不是server.port。然後,某些載入程式會意外合併或失敗,並顯示「此處不允許對應值」。浪費最多工程時間的 JSON 到 yaml 錯誤類別正是這樣的:解析為錯誤的樹的看起來有效的文本。

修復: 選擇一個縮排寬度(2 個空格),禁止提交的 YAML 中的製表符,以及針對已知良好的發射器(yq、您的 IDE 或 YAML Validator)的 diff 轉換器輸出。如果您需要從頭開始的可重複工作流程,請在自動化管道之前參閱how to convert JSON to YAML

編輯器功能使情況變得更糟:插入製表符的「片段」、僅重排檔案一半的漂亮印表機,或在移動空格時標準化 CRLF 的貼上緩衝區。當偵錯 JSON 到 yaml 錯誤時,在責怪轉換器之前,明顯地折疊空白(cat -A或 IDE“渲染空白”)。

json
{ "server": { "host": "0.0.0.0", "port": 8080 }}

資料類型問題

JSON 文字是明確的:truefalsenull、數字、字串。 YAML 1.1(在野外仍很常見)在不加引號時將 yes/no/on/off 視為布林值。 JSON 永遠不會發出這些標記,但人們在轉換後編輯 YAML 有時會引入它們,或透過另一個工具交換引用的往返。

更糟的是:YAML 中不帶引號的 null 很好,但雜散的 NullNULL 可能會根據解析器模式而表現不同。時間戳記也是如此:如果載入器允許,像 2024-01-15 這樣的字串可能會變成 日期類型

根據解析器的不同,yes會變成布林值truenull保持為 null,而cutoff可能會變成已解析的日期,而不是原樣的字串,這會破壞需要逐字接收"2024-01-15"的 API。

修復:引用任何必須保留字串的內容:當合約需要單字「yes」時,enabled: "yes",當消費者比較字串時,cutoff: "2024-01-15"。轉換後,在測試或模式驗證中斷言類型(JSON 模式、OpenAPI 或 CI 中的嚴格 YAML 載入器)。

數位驚喜也很重要:JSON001無效; YAML 可能會根據版本不同地以不同方式解析前導零標記。在轉換之前堅持使用 JSON 正常形式,然後引用必須保留前導零的識別碼(郵遞區號、視為字串的版本段)。

yaml
flags: enabled: yes region: null cutoff: 2024-01-15

數組格式化問題

JSON 陣列以[]為界;序列項不能「漂移」。 YAML 清單使用-標記,其縮排等級決定哪個物件擁有這些項目。 JSON 到 yaml 自動化後的一個典型失敗是單元素數組變成內聯標量,或者列出粘附到錯誤父鍵的項目。

{"items": [{"id": 1}, {"id": 2}]}這樣的 JSON 必須成為在items:下縮排的-列表。如果一個-縮進,你會突然出現多個文件或解析錯誤。多行字串和巢狀清單放大了問題——Kubernetes 清單和 CI 配置都充滿了這兩種情況。

空數組很重要:JSON 中的[]應該成為顯式的 YAML 列表語法(items: []items:\n []模式,取決於樣式)——避免像items:這樣不明確的標量,後面沒有任何內容,除非你的 linter 禁止它。混合數組(一個列表中的物件和字串)是有效的 JSON,但展平後很容易出現縮排錯誤。

修復:轉換後永遠不要手動合併清單標記;當清單看起來可疑時從 JSON 重新產生。目視驗證每個-與其兄弟姐妹共用同一列,並且比它所屬的鍵更深

範例:在轉換後完好無損的列表

從 JSON{"routes": [{"path": "/api", "upstream": "svc"}, {"path": "/health", "upstream": "direct"}]}開始,穩定的 YAML 將同級-塊保持對齊:

如果upstream: directroutes:下對齊,而不是在第二個- path下對齊,則您剛剛發明了一個不同的路由表 - 一個微妙的 JSON 到 yaml 錯誤類,它傳遞 lint 但會中斷路由。

yaml
routes: - path: /api upstream: svc - path: /health upstream: direct

特殊字元

包含:#{}[]或前導-的字串需要在 YAML 中引用,否則掃描器開始意義附加到標點⧟開始映射)值)。 URL 和connection_string值是常見的受害者。

#之後的所有內容都可以視為註釋,除非您引用:

`yaml
message: "Error: disk full (see log #42)"
`

修正:採用一個簡單的規則:如果值看起來像程式碼、URL,或包含#: ,請將其用雙引號括起來,並在需要時將內部"轉義為\"

來自 JSON (\\n) 的多行字串有時會在工具跳躍期間分解為 YAML 文字 (|) 或折疊 (>) 區塊 — 如果每個下游載入器都同意的話,那沒問題。如果沒有,請保留引號的單行轉義,直到標準化為止。

yaml
message: Error: disk full (see log #42)

如何避免錯誤

JSON → YAML 視為編譯步驟,而不是一次性貼上:

  • JSON to YAML 中執行轉換(本機瀏覽器內處理),然後在合併前使用 YAML Validator 進行驗證。
  • 如果您的 linter 支援yamllint樣式規則,則 YAML 中的標籤和不明確的標量上的 CI 會失敗。
  • 保留黃金樣本:具有邊緣情況的小型 JSON 輸入(null、空數組、帶冒號的字串)並斷言字節穩定或 AST 穩定的 YAML 輸出。

當錯誤仍然存在時,來源 JSON 上的 JSON Validator 會在「垃圾」情況變得令人困惑的 YAML 樹之前消除一半。

如果您在轉換後將設定傳送到 Kubernetes,請將此清單與Convert JSON to YAML for Kubernetes (With Examples)中已完成的清單演練結合。

大多數 JSON 到 yaml 錯誤並不神秘 — 它們是 縮排、隱式類型、列表所有權或引用。讓這四個維度變得非常明確,你的配置將在晚上 11 點停止失敗。在部署之夜。