要在將 JSON 轉換成 Rust 結構後檢查結果,請將一個具有代表性的嚴格 JSON 樣本貼到 JSON to Rust Struct Converter,檢視它所輸出的推斷數值寬度、Option 包裹型別、巢狀型別名稱以及 serde 重新命名屬性,然後將該原始碼複製到啟用 Serde 的 Cargo 專案中,進行格式化、編譯,並使用 serde_json 對你真實的 JSON 測試資料進行往返測試。產生器只會輸出原始碼文字,不會進行編譯、上傳或執行任何動作,因此驗證工作必須由你這端完成。請將輸出的原始碼視為一份可審閱的草稿,它由一項觀察所形塑:工具所做的每一個選擇——owned String、i64、f64、bool、Vec、Option、serde_json::Value、正規化的 snake_case 欄位,以及保留字安全的後綴——全都是從單一嚴格 JSON 輸入推導而來,而不是來自權威的 API 描述。因此,檢查流程會結合三個階段:靜態閱讀輸出的原始碼、在實際引入 serde derive 支援的 Rust 專案中進行建構,以及進行一項行為測試,對你真實的測試資料進行解碼與重新編碼,以確認推斷的型別能夠接受實際生產環境所送出的內容。

how do i check the result after i convert json to rust struct
在 JSON 轉換後檢查產生的 Rust 結構

為何產生的 Rust 原始碼仍需要審閱

單一樣本的推斷刻意保持保守,因此輸出僅反映剖析器所見到的內容,而不會多做任何假設。你貼上的 JSON 中出現的欄位會被視為必填,而在某一個合併物件樣本中缺少的鍵則會變成 Option。同時包含整數與小數的數值觀察會合併為 f64;JavaScript 剖析器無法精確表示的 JSON 整數,會從 i64 推斷退一步;而互不相容的證據則會變成 serde_json::Value,而不是被猜測為某個列舉。由於這些規則,第一步驗證就是閱讀產生的原始碼,確認每個欄位都符合你真實 API 或檔案格式所使用的形狀。跳過這個閱讀步驟正是生產環境 bug 出現的原因:需要 u64 的小整數、UUID 形式的字串、借用的切片、日期字串,或是帶標籤的列舉,都無法從單一樣本推斷出來;轉換器的設計正是為了將這種不確定性標示出來,而不是將其隱藏。

檢查推斷的型別、Option 與重新命名

針對產生的原始碼進行驗證時,應該逐行檢查,確認這些型別與你資料實際包含的內容相符。下表摘要說明了轉換器在解析嚴格 JSON 時所套用的對應規則,這些規則直接取自已發佈的推斷規則。

JSON observationInferred Rust typeVerification note
String valueStringOwned String;若 API 採用借用或承載 UUID、日期或 URL,請改為 &str;或使用 newtype。
Booleanbool除非線上資料使用 0/1,否則不需要替代方案。
Integer within safe rangei64推斷前會先經過 JavaScript 解析,因此不安全的數字表示會退一步採用 f64——請將對精度敏感的識別碼保留為字串。
Decimal or mixed numberf64請確認該欄位是否確實需要 f64,或是改用定點數 / Decimal 型別。
Array of observed elementsVec of merged element type空陣列會變成 Vec<serde_json::Value>,因為無法建立任何元素型別。
Null aloneOption<serde_json::Value>由於未觀察到具體型別,因此以 null 取代。
Null combined with an observed typeOption<T>僅代表已觀察到的缺失情況;生產環境可能需要更嚴格或更寬鬆的契約。
ObjectPublic struct with Serialize, Deserialize, Debug巢狀物件會成為以路徑安全推導出的具名巢狀結構。
Incompatible mixed valuesserde_json::Value在定義真正的契約之前,會保留其不確定性。

識別碼同樣需要仔細檢查。JSON 鍵會被轉換為 ASCII snake_case,開頭為數字時會加上前綴,Rust 保留字會加上尾部下劃線,而正規化時發生的衝突則會加上數字後綴。每當產生的 Rust 欄位名稱與原始 JSON 鍵不同時,產生器會新增 serde 重新命名屬性,以確保線上的名稱仍能對應——例如,JSON 鍵「userId」會變成 user_id 並加上 #[serde(rename = "userId")]。請逐一親自檢查每個重新命名:衝突與保留字處理是在反序列化期間最常見、卻最不易察覺的來源。

設定啟用 Serde 的專案以進行驗證

因為轉換器只會輸出原始碼文字,所以下一步檢查結果的工作,就是把這段文字放到一個可以實際編譯的地方。建立一個小型 Cargo 專案,在其 Cargo.toml 中鎖定相容版本的 serde 與 serde_json,並加入產生的模組——轉換器的匯入方式預期具備 serde derive 支援,而目的端的剖析通常也需要 serde_json。本頁面本身不會新增任何相依套件,因此任何因版本缺失或不相符而造成的編譯失敗,都是屬於你專案的問題,而非產生器的問題。一旦原始碼能夠乾淨地編譯,請執行 cargo fmt,讓這段程式碼符合你專案的風格,並在你將其複製到正式 crate 時保持較小的 diff。

一個實用的驗證習慣是:將產生的原始碼暫時放在一個臨時模組中,並撰寫一個簡短的健全性測試,該測試會在一個具有代表性的測試資料上呼叫 serde_json::from_str,並對產生的結構呼叫 serde_json::to_string。這項往返測試是確認推斷的型別實際上與資料所承載內容相符的最強力手段,同時它也會暴露出靜態閱讀所無法察覺的問題——例如某個欄位在 API 的某些路徑中以字串形式回傳,在其他路徑中卻以整數形式回傳,而產生器基於樣本的推斷只能反映其中一種形狀。

使用 serde_json 對真實 JSON 進行往返測試

若要以行為層面的方式檢查轉換後的結果,你至少需要三組測試資料:一組涵蓋典型形狀的成功路徑、一組用於驗證可選欄位或重新命名欄位的第二個成功路徑,以及一組會產生非預期輸入的失敗路徑。請使用 serde_json::from_str::<YourStruct> 來剖析每一組資料,並斷言其欄位會解碼為你所預期的值。接著,使用 serde_json::to_string 將這些結構重新序列化,並確認輸出的 JSON 符合線上的形狀,特別留意經過重新命名的欄位與 Option 包裹型別。若某個欄位在 API 實際有送值的情況下卻解碼為 None,最可能的原因就是靜態閱讀時漏掉了 serde 重新命名屬性,或是產生器以你未注意到的數字後綴解決了某個鍵衝突。

為了多一層信心,可以在專案上執行 cargo clippy 並閱讀其警告——這些警告通常會標明明顯的推斷落差,例如:整個結構充滿了 serde_json::Value 欄位,而這些欄位其實適合改用手寫的列舉;或是某個推斷為 f64 的數值欄位,本應使用較小的整數型別。當測試資料來自不同的 API 版本時,往返測試也同樣有幫助:將每個版本的測試資料分別貼入轉換器,並並排比較產生的原始碼,因為兩者之間的差異通常會精確指出你在正式採用推斷型別之前,必須強化的可選欄位與重新命名規則。

單一樣本推斷的限制

從單一樣本進行的推斷,無法建立 API 契約。你貼上的 JSON 中出現的欄位,在其他地方可能是可選的;某個小整數在生產環境中可能需要 u64、i128、定點小數或字串;某個字串則可能代表 UUID、日期、URL、列舉、借用的切片或密鑰。確實會改變形狀的混合物件,可能適合使用帶標籤的列舉來表達,而這是產生器無法從單一觀察中發明出來的。內建於該工具的八組外部測試資料涵蓋了 String、i64、f64、bool、Vec、Option、null 以及保留字重新命名語法,其他測試則涵蓋了巢狀結構、正規化衝突以及無效輸入——但它們並不會改變背後的根本原則:單一樣本只是一份起點草稿,而非最終契約。

實際的限制對於驗證同樣重要。工作範圍上限為輸入字元 500,000、數值 50,000、巢狀層級 40,以及輸出字元 1,000,000,且必須採用嚴格 JSON,註解、尾端逗號、NaN、Infinity、BigInt 語法、undefined 以及 JavaScript 物件實字皆會被拒絕。JSON 數字在推斷前會由 JavaScript 進行剖析,因此不安全的整數表示無法被精確表示,並會從 i64 推斷退一步——只要數值跨越數值邊界,請在來源契約中將對精度敏感的識別碼與小數保留為字串。產生器不會新增 crate 路徑、模組可見性政策、生命週期、泛型、自訂序列化器、deny_unknown_fields、預設值、扁平化、標籤化或驗證,因此上述任何你所需行為,都必須在推斷出來的原始碼通過檢查之後,由你手動撰寫。

如果你正在權衡各種方案,JSON to XML API Alternative: A Browser-Side Path 對此有詳細說明。