JSON to Zod Schema Converter 頁面並不會安裝或執行 Zod。它是一個源碼產生器,接收一個有效的 JSON 值,以 JSON.parse 嚴格解析,並回傳可閱讀的 Zod 原始碼文字以及推斷出的 TypeScript 型別。沒有任何資料會被上傳,也沒有捆綁任何驗證函式庫,產生的程式碼不會在頁面上執行。你會收到一串 import 陳述式、一個 schema 宣告,以及一個 z.infer 別名,讓你能在複製到任何地方之前逐行檢視。由於 Zod 本身從未被載入到頁面中,轉換器的執行階段負擔維持得很輕,你的範例也從未離開過瀏覽器分頁。這個頁面的契約刻意做得狹窄:產生一個乾淨的起始 schema,反映在範例中所觀察到的內容,然後交還給你,由你在已將 Zod 列為相依套件的專案中進行安裝、編與驗證。理解這道界線,才能避免把單次觀察誤當成保證的 API 契約。

這個頁面實際做了什麼、沒有做什麼
JSON to Zod Schema Converter 執行四個有界線的動作,並明確避開第五個動作。它接受一個嚴格的 JSON 範例與一個有效的 JavaScript 識別符,在本機執行確定性的推斷,回傳 import 程式行、schema 宣告以及 z.infer 型別,並穩定化相同的 union,使得重複轉換同一輸入會產生相同的原始碼。它不做的那個動作,是提供執行階段:它不會把 Zod 載入頁面、不會 eval 產生的程式碼,也不會嘗試透過套件管理工具將任何東西安裝到你的專案中。由於解析器完全在瀏覽器中執行,因此也不存在上傳步驟。這樣的分離正是這個頁面能夠維持零相依、卻仍產生出合乎慣例的 Zod 原始碼的原因。
由此衍生出兩個實際的後果。第一,你複製的輸出是純文字 —— 頁面中沒有內嵌任何可執行的產物,因此當你將它貼到 TypeScript 檔案的那一刻,你就必須為安裝對應的 zod 版本,以及在你專案自己的工具鏈下編譯該檔案,負起完全的責任。第二,由於頁面上並沒有任何東西實際執行該 schema,轉換器無法告訴你你的範例是否忠實代表實際環境的資料;它只能告訴你這個範例本身包含了什麼。如果你需要對真實契約進行確認,你必須把具代表性的 fixture 與 API 說明文件帶到已安裝 Zod 的專案中進行。
推斷引擎如何將 JSON 對應到 Zod
轉換器會迴地走訪已解析的 JSON 樹狀結構,從一組固定的建構子中發出 Zod 建構式,並以確定性的順序排列,使輸出保持穩定。對應 JSON 基本型別的對映遵循 Zod 已記錄的介面,你可以對照 Zod API 參考文件 逐一確認每個建構式。
| 觀察到的 JSON 值 | 發出的 Zod 運算式 | 備註 |
|---|---|---|
| String | z.string() | 不會推斷格式(沒有 .email()、.url()、.uuid())。 |
| 有限數字 | z.number() | 已通過 JSON.parse;不會加上整數或範圍的限制。 |
| Boolean | z.boolean() | 直接對應。 |
| null | z.null() | 與另一個型別結合時,在 union 上會變成 .nullable()。 |
| Object | z.object({...}) | 屬性順序依照出現順序;不安全的鍵會以 JSON 跳脫字元加上引號。 |
| Array(同質) | z.array(element) | 從範例中取得的單一元素 schema。 |
| Array(混合基本型別) | z.array(z.union([...])) | 依確定性順序排列並去除重複。 |
| 空陣列 | z.array(z.unknown()) | 明確標示不確定 —— 沒有任何元素證據。 |
物件一次以一個屬性進行推斷,轉換器會記住哪些鍵在每個取樣物件中都出現過,哪些只在部分物件中出現。在每個範例中都出現的屬性會以 required 發出;至少在一個範例中缺席的屬性則會加上 .optional() 變成選用。當兩個範例在同一個鍵下對型別意見不一致時,這些值會被遞迴合併成一個 union。物件陣列的行為也是如此:其內部鍵會跨元素物件進行合併,缺失的欄位在合併後的元素 schema 中會變成選用。巢狀陣列與巢狀物件以相同的遞迴處理,最多支援 40 層的深度。
讓產生的 Schema 在你的專案中跑起來
由於這個頁面只發出原始碼文字,任何涉及實際 Zod 執行階段的步驟都發生在你的電腦上。以下的有序工作流程涵蓋了讓 schema 能驗證真實資料、而不只是描述單一範例所需的最低限度工作。
- 在專案中鎖定 Zod 版本。執行套件管理工具的安裝指令,安裝與轉換器所發出建構式相符的主要版本(目前為 Zod)。在 package.json 中鎖定確切版本,讓正式環境與測試環境對 schema 介面保持一致。
- 建立 schema 檔案並貼上產生的原始碼。將 import 那一行、schema 宣告,以及 z.infer 別名放入你原始碼樹狀結構下的一個 TypeScript 檔案,例如 src/schemas/user.ts。將這個檔案視為你專案中任何其他模組一樣處理。
- 格式化並編譯。對新檔案執行格式化工具(Prettier 或同等工具),讓引號、縮排與 import 順序與程式碼庫其他部分一致,接著以 tsc --noEmit 進行編譯,確認產生的 TypeScript 型別與你預期的使用方式吻合。
- 將 schema 接上你的驗證呼叫點。在資料進入的邊界(API 處理器、表單提交、訊息佇列消費者),以 YourSchema.parse(payload) 取代任何鬆散的執行階段檢查。若原始碼宣告了 .optional() 或 .nullable(),請在取用端程式碼中如實反映這些預期。
- 測試接受與拒絕的正式環境案例。新增單元測試,將具代表性的真實 API fixture 以及刻意無效的負載,丟到 .safeParse 上執行。確認 schema 接受契約所承諾的內容,並拒絕契約所禁止的內容。只有這些測試能證明推斷結果與權威說明文件一致。
- 補上轉換器無法推斷的規則。手動加上 .min()、.max()、.int()、.email()、.uuid()、.regex()、refinements、transformations、defaults、discriminated unions、brands,以及任何商業規則。將這些視為來自 API 說明文件、而非來自範例本身的契約決策。
範例推斷的不足之處
單一最重要的警語是:轉換器描述的是單一範例中的觀察結果,而不是你的服務所承諾的契約。你貼上的物件中出現的欄位,在其他端點省略時仍可能於正式環境中是選用的;而範例中缺席的值,在別處也可能是完全有效的。如需更深入了解此限制如何影響實際工作流程,請參考 以範例驅動轉換的推斷限制指南。產生器刻意避免猜測下列項目,因為拼字差異與小型範例無法確立意圖:字串格式(例如 email、URL、UUID、date-time)與 regex 樣式;數字的最小值、最大值與整數限制;列舉成員與字面值;依標籤區分的 discriminated union;迴參考;records、tuples 與嚴格物件行為;brands、coercions、defaults 與 transformations;以及任何存在於 JSON 形狀之外的商業規則。以上每一項都應該出現在你手動新增的內容中,並以 API 說明文件或具代表性的 fixture 集合作為依據,而非依賴推斷本身。
有兩個具體情況值得特別注意。第一,空陣列會產生 z.array(z.unknown()),而不是 z.array(z.string()) 或 z.array(z.never()),因為並沒有任何元素證據;若你的端點實際上確實只會發出字串,你就必須自行將其收緊。第二,帶有空格、連字號、數字開頭或引號的屬性名稱,會以 JSON 字串跳脫的形式發出,使產生的物件常值仍然是有效的 JavaScript;這保留了正確性,但意味著產生的鍵名不會符合乾淨的識別符風格,除非你在檢閱時明確重新命名。
硬性限制與嚴格解析行為
轉換器在四個軸向上設有界線,只要其中任何一項被超出,就會回傳明確的錯誤,而不是截斷或發出部分的 schema。輸入的 JSON 不得超過 500,000 字元;走訪過程不得拜訪超過 50,000 個值;巢狀深度不得超過 40 層;產生的原始碼不得超過 1,000,000 字元。由於引擎拒絕在這些限制之外進行猜測,即使是一個符合預算但非常深或非常寬的範例,本身仍可能是不佳的契約文件,因此建議的作法是餵入一個具代表性的小型 fixture,並將獨立的負載拆分到不同的 schema 中。
解析發生在推斷之前,這代表轉換器直接使用 JSON.parse。JavaScript 註解、尾端逗號、NaN、Infinity、undefined、BigInt 語法、單引號字串,以及裸的物件常值,都會被拒絕而非默默修復。數字在 JSON 解析後亦遵循 JavaScript 的精度,因此需要精確十進位語意的識別符、貨幣或計數,通常應在你的範例中維持為字串。混合值的 union 會以確定性的順序排列,相同的 schema 會去除重複,因此對同一輸入重新執行轉換器,總會產生位元層級完全一致的原始碼。這種可重現性,正是讓你能將輸出視為審閱產物的基礎:貼上它、進行 diff,並在鎖定到專案之前與真實契約相互比對。
如需更深入的了解,請參閱 如何在瀏覽器中驗證 JSON 檔案。