JSON 轉 Rust 結構轉換器可從單一嚴格 JSON 樣本推導出可直接搭配 Serde 使用的 Rust 結構,並為每個產生的公開型別加上 SerializeDeserializeDebug 衍生,整個過程既不需上傳樣本,也不用安裝任何 crate。此工具接收一份具代表性的 JSON 文件,在瀏覽器中以嚴格 JSON 進行解析,並遞迴走訪每個值來選擇 Rust 基本型別、容器、巢狀結構或 Option 包裝。字串對應到擁有的 String,布林值對應到 bool,安全的 JSON 整數對應到 i64,其他所有 JSON 數字則對應到 f64。陣列會變成 Vec<T>,null 會變成 Option,巢狀物件則會成為已附加 serde 衍生的具名公開結構。由於推論僅依據單一樣本執行,所產生的原始碼屬於可審閱的版本而非最終定案——在作為契約發佈之前,每個數值寬度、可選欄位與識別名稱調整都仍需由人工把關。本文的其餘部分將說明轉換器會輸出什麼內容、所遵循的型別對應規則,以及如何將產生的原始碼整合到啟用 Serde 的 Cargo 專案中。

convert json to rust struct
convert json to rust struct

轉換器輸出的 Rust 原始碼

此頁面僅輸出 Rust 原始碼文字。它不會編譯程式碼、執行程式碼,也不在你的專案中加入任何 crate。每個公開結構都帶有標準的衍生三重奏——SerializeDeserializeDebug——並使用 serde 屬性語法,使所產生的 import 預設假設目標環境已啟用 Serde。巢狀物件不會被扁平化、不會加上標記,也不會以匿名方式呈現;每個巢狀物件都會成為自己專屬的具名公開結構,而從根型別一路延伸至該巢狀物件的路徑,會提供一個具確定性且不會碰撞的名稱。

輸出的原始碼不包含任何 use 陳述式、mod 宣告、生命週期參數、泛型參數或自訂序列化器。沒有 deny_unknown_fields、沒有 default、沒有扁平化、沒有標記,也沒有驗證掛鉤。輸出內容僅是讓 Serde 能往返處理符合你所貼上樣本的酬載所需的最基本介面,將所有策略決策留給審閱並採用此程式碼的開發人員。

產生器使用的 JSON 對 Rust 型別對應規則

下表反映了產生器對單一樣本套用的規則。在證據不明確的情況下,產生器會退而採用 serde_json::Value,而非猜測列舉或強制轉換型別。

JSON 觀察結果產生器輸出的 Rust 型別
字串值String
布林值bool
安全的 JSON 整數i64
其他任何 JSON 數字f64
整數與小數混合f64
非空陣列合併元素型別 T 的 Vec<T>
空陣列Vec<serde_json::Value>
未觀察到其他型別的 nullOption<serde_json::Value>
與型別 T 並存的 nullOption<T>
JSON 物件帶有 SerializeDeserializeDebug 的公開結構
巢狀 JSON 物件具名巢狀公開結構,型別名稱衍生自路徑
每個物件皆出現的物件陣列欄位必填(非 Option)欄位
任何物件中遺漏的物件陣列欄位Option<T> 欄位
不相容的混合值serde_json::Value

三步驟從 JSON 產生 Rust 結構

端對端的工作流程刻意設計得很短。你貼上嚴格 JSON、產生原始碼,然後將其帶入已串接 Serde 的 Cargo 專案。

  1. 貼上嚴格 JSON 並輸入 ASCII 根型別名稱。樣本可以是 JSON 物件、陣列或基本型別;產生器需要嚴格的子集,因此註解、尾端逗號、NaNInfinity 以及 JavaScript 風格的物件實字皆會被拒絕。請挑選一個有效 Rust 識別名稱——ASCII 字母、數字與底線,且不能是保留關鍵字——因為該名稱會成為輸出原始碼最上方的公開結構。
  2. 產生並審閱輸出內容。請掃描原始碼中會改變形狀的五個細節:數值寬度(安全整數 vs f64)、Option 包裝、退而採用 serde_json::Value 的混合型別欄位、巢狀結構名稱,以及當 Rust 欄位與 JSON 鍵不同時使用的 #[serde(rename = "...")] 屬性。若其中任何一項不符合你的真實資料,請在貼入專案前手動編輯。
  3. 複製到啟用 Serde 的 Rust 專案。將結果加入一份 Cargo.toml,其中固定(pin)一個啟用 derive 功能的 serde 版本(若你打算在目的地端解析 JSON,則再加上 serde_json),執行 cargo fmt、執行 cargo build,並透過 serde_json::from_strserde_json::to_string 對具代表性的 fixture 進行往返測試,以確認樣本與結構彼此一致。

識別名稱正規化與 Serde 重新命名屬性

JSON 鍵並非 Rust 識別名稱。產生器會將每個鍵翻譯成不會碰撞的 ASCII snake_case 欄位,並在線上鍵與 Rust 欄位不同時附上 #[serde(rename = "...")] 屬性,以完整保留線上名稱。規則具有確定性:

JSON 鍵的形態輸出的 Rust 欄位
已是 snake_case同名稱;無 rename 屬性
camelCase、空格、標點或連字號在每個邊界處加上底線;rename 保留原始線上鍵
前導數字(例如 2fa_enabled加上底線前綴;rename 保留線上鍵
Rust 關鍵字(例如 typeref加上尾端底線;rename 還原原始鍵
兩個鍵正規化後變成相同識別名稱在第二個鍵加上數字後綴;rename 還原原始鍵

巢狀結構的名稱遵循相同的紀律:從根型別一路延伸至每個巢狀物件的路徑,會提供具確定性且不會碰撞的名稱。你可以在專案中自由重新命名,但產生器輸出的第一版已能與原始酬載正確往返。

產生器拒絕的輸入與硬性限制

由於此產生器是嚴格 JSON 解析器,數種常見的 JSON 形式輸入會在第一時間就失敗。註解、尾端逗號、NaNInfinity、BigInt 風格的後綴、undefined 以及 JavaScript 物件實字皆不被接受——若你的樣本來自手動編輯的檔案,請在貼上前先透過 JSON 有效性檢查 進行驗證。此外,JSON 數字在推論送達型別選擇器之前,會先由 JavaScript 引擎進行解析,因此無法以 i64 精確表示的整數值會退而採用 f64 而非 i64;若精確度至關重要——例如 BigInt 識別名稱、貨幣最小單位或十進位科學量測——請在來源契約中將這些欄位保留為字串。

處理量上限為 500,000 個輸入字元、50,000 個值、40 層巢狀深度,以及 1,000,000 個輸出字元。任何超出這些上限的內容會回傳錯誤而非部分輸出。八個外部 fixture 鎖定了邊界情況——Stringi64f64boolVecOptionnull,以及 Rust 關鍵字重新命名語法——其他額外測試則涵蓋巢狀結構、正規化碰撞與無效輸入的拒絕處理。整個流程沒有上傳步驟:樣本從不離開瀏覽器。

將產生的原始碼整合進 Serde 專案

產生的結構只有在已串接 Serde 的專案中才有用。啟用 Serde 的專案所需的最小 Cargo.toml 項目,是一個啟用 derive 功能的 serde 依賴項,以及用於目的地端 JSON 解析的 serde_json 依賴項。產生器並不會替你加入這兩項,因此請自行固定相容的版本——典型的搭配是 serde 第 1 版並啟用 derive 功能,以及 serde_json 第 1 版,兩者皆可從 crates.io 解析取得。

一旦依賴項解析完成,請將產生的原始碼貼入模組,執行 cargo fmt、執行 cargo build,並確認該型別能夠編譯。接著測試真實的線上格式:使用 serde_json::from_str::<YourRoot>(&payload) 對 fixture 進行解序列化,再使用 serde_json::to_string(&value) 將結果序列化回去,並將往返結果與原始樣本進行 diff 比對。往返測試就是驗證的關鍵時刻——若產生器標記為 Option 的欄位在正式環境中其實是必填,或某個數值在契約預期為 u64i128 或十進位型別時卻退而採用 f64,你都會在此時看出來。官方的 Serde derive 指南與 Rust 識別名稱參考 是確認你所採用語法的正確出處。

Why the Output Is Reviewable, Not Authoritative

Inference from one sample cannot establish an API contract. A field present in the sample may be optional elsewhere; a small integer may need u64, i128, a decimal crate, or a string elsewhere; a string may represent a UUID, an ISO 8601 date, a URL, an enum variant, a borrowed slice, or a secret that should never reach logs; and mixed objects may deserve a tagged enum rather than a flat struct. Before adopting the generated source, review authoritative API documentation and run several success and failure fixtures — including malformed payloads, missing fields, and extra fields — through the same round-trip described above. The generator's job is to remove the typing chore; the contract stays yours.

If you want to start from a representative sample and produce the corresponding Serde-ready struct, the JSON to Rust Struct Converter runs the inference locally and hands you a copy-ready module. Format and compile the copied source, then round-trip representative JSON with serde_json before adopting it.

If you're weighing options, Minify JSON in VS Code Without Breaking Numbers covers this in detail.