這個工具的用途
使用步驟
貼上 JSON(或載入範例),即可在右側讀到 C# class。在選項面板設定 namespace,檔案可直接落入你的專案;預設輸出採用 Newtonsoft.Json attribute。
輸入: {"id":42,"name":"devsmiths","createdAt":"2024-03-11T08:24:00Z","stars":1280,"public":true,"contributors":[{"login":"ada","commits":51,"admin":true},{"login":"linus","commits":33,"admin":false}],"homepage":null}
輸出(C#):
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Devsmiths
{
public partial class Root
{
[JsonProperty("id")] public long Id { get; set; }
[JsonProperty("name")] public string Name { get; set; }
[JsonProperty("createdAt")] public string CreatedAt { get; set; }
[JsonProperty("stars")] public long Stars { get; set; }
[JsonProperty("public")] public bool Public { get; set; }
[JsonProperty("contributors")] public Contributor[] Contributors { get; set; }
[JsonProperty("homepage")] public object Homepage { get; set; }
}
public partial class Contributor
{
[JsonProperty("login")] public string Login { get; set; }
[JsonProperty("commits")] public long Commits { get; set; }
[JsonProperty("admin")] public bool Admin { get; set; }
}
}限制與邊界情況
- 預設輸出針對 Newtonsoft.Json(
JsonProperty)。 要切到 .NET 6+ 的 System.Text.Json,只需 find/replace:JsonProperty→JsonPropertyName、using Newtonsoft.Json→using System.Text.Json.Serialization——屬性形狀完全相同。 - 屬性是
public自動屬性(get; set;), 不是 records。C# 9+ records 形狀無法靠原樣通過 System.Text.Json 來回(records 的 primary constructor 需要[JsonConstructor]加上排序好的參數)——對語法層產生器超出範圍。 - Nullable reference type 沒有標記。若專案 csproj 開啟
<Nullable>enable</Nullable>,請手動為 reference type 加上?(或接受警告)。Value type(long、bool)會自動以?標示樣本中為null的位置。 - 日期字串保持為
string,不是DateTime/DateTimeOffset。ISO 8601 字串無歧義,但混用序列化 attribute 來處理日期轉換很脆弱——若需要型別化日期, 請寫自訂JsonConverter。 - 陣列輸出為
T[]而非List<T>。 Newtonsoft.Json 與 System.Text.Json 都能正確反序列化兩者; 若 runtime 需要.Add(),請手動改為List<T>。 - 單樣本推論:樣本中缺漏的鍵不會自動變 nullable。切換 all optional 套用全部欄位。
常見問題
- Newtonsoft.Json 還是 System.Text.Json — 輸出針對哪個?
- 預設是 Newtonsoft.Json(`[JsonProperty]` attribute、`using Newtonsoft.Json`)。Newtonsoft 較寬鬆且在 legacy 專案中較普遍。要切到 .NET 6+ 的 System.Text.Json,find/replace:`[JsonProperty("foo")]` → `[JsonPropertyName("foo")]`、`using Newtonsoft.Json` → `using System.Text.Json.Serialization`。屬性形狀完全相同。
- 為什麼 C# 9+ 不產生 records?
- Records 看似合適(不可變、值相等、行數少),但 primary constructor 參數無法直接通過 System.Text.Json 來回——需要 `[JsonConstructor]` annotation 與精確的參數順序,容易出錯也容易悄悄錯位。產生器堅持 `public class { get; set; }` 屬性,因為兩種序列化器都能零配置來回。
- 如何讓 nullable reference type 與 #nullable enable 相容?
- Value type(long、bool)在樣本含 null 時會自動加上 `?`。Reference type(string、object)不會——產生器輸出時不標記。若專案開啟 `<Nullable>enable</Nullable>`,請手動為可能為 null 的欄位加 `?`。產生器保守在此,因為把所有東西都標為 `string?` 會把 null check 推到呼叫端,可能不是你要的。
- ISO 8601 日期字串可以變成 DateTime / DateTimeOffset 嗎?
- 不會自動——日期字串保持為 `string`。變通做法:把欄位型別改為 `DateTime`,讓序列化器預設的 ISO 8601 解析來處理(.NET 7+ 的 System.Text.Json 支援);或為含時區資訊的欄位寫 `JsonConverter<DateTimeOffset>`。對 wire-format 日期通常 DateTimeOffset 是正確選擇。
- 為什麼陣列用 T[] 而不是 List<T>?
- T[] 大小固定,配置成本較低且 Span 相容;List<T> 可變但配置 overhead 較高。產生器選 T[] 是因為反序列化兩者效果相同,瘦型別是更好的預設。對需要在領域程式碼中變動的集合,可手動改為 List<T>。
- JsonProperty("…") attribute 實際在做什麼?
- 它告訴 Newtonsoft.Json(改名後對 System.Text.Json 同樣)該屬性對應的 JSON 鍵是什麼。C# 慣例是 PascalCase 屬性名、JSON 慣例是 camelCase 或 snake_case——attribute 在兩者之間架橋。沒有它,Newtonsoft 會 fallback 到大小寫不敏感比對,通常能運作但較慢、較隱晦;明確的 attribute 更清楚也更快。
內容審閱者:ShiangYu Huang