從 Newtonsoft.Json 移轉至 System.Text.Json
本文說明如何從 移 Newtonsoft.Json 轉至 System.Text.Json 。
System.Text.Json
命名空間提供從 JavaScript 物件標記法序列化和還原序列化的功能。 連結 System.Text.Json
庫包含在 .NET Core 3.1 和更新版本的運行 時間中。 針對其他目標架構,請安裝 System.Text.Json NuGet 套件。 套件支援:
- .NET Standard 2.0 和更新版本
- .NET Framework 4.7.2 和更新版本
- .NET Core 2.0、2.1 和 2.2
System.Text.Json
主要著重于效能、安全性和標準合規性。 它在預設行為方面有一些主要差異,且不會將功能與 同位。 Newtonsoft.Json
在某些情況下, System.Text.Json
目前沒有內建功能,但建議的因應措施。 在其他案例中,因應措施是不切實際的。
我們正在投資新增最常要求的功能。 如果您的應用程式相依于遺漏的功能,請考慮 在 dotnet/runtime GitHub 存放庫中提出問題 ,以找出是否可以新增案例的支援。
本文的大部分內容都是關於 JsonSerializer 如何使用 API,但也包含如何使用 JsonDocument 的指引(代表檔物件模型或 DOM), Utf8JsonReader 以及 Utf8JsonWriter 類型。
在 Visual Basic 中,您無法使用 Utf8JsonReader ,這也表示您無法撰寫自訂轉換器。 此處呈現的大部分因應措施都需要您撰寫自訂轉換器。 您可以在 C# 中撰寫自訂轉換器,並在 Visual Basic 專案中註冊它。 如需詳細資訊,請參閱 Visual Basic 支援 。
差異資料表
下表列出 Newtonsoft.Json
功能和 System.Text.Json
對等專案。 對等專案分為下列類別:
- ✔️ 內建功能支援。 取得類似的行為
System.Text.Json
可能需要使用屬性或全域選項。 - ⚠️ 不支援,但可能因應措施。 因應措施是 自訂轉換器 ,可能無法提供功能
Newtonsoft.Json
的完整同位。 針對其中一些,範例程式碼會以範例的形式提供。 如果您依賴這些功能Newtonsoft.Json
,移轉將需要修改 .NET 物件模型或其他程式碼變更。 - ❌ 不支援,且因應措施不實用或可能。 如果您依賴這些功能
Newtonsoft.Json
,則移轉將無法進行,而不會有重大變更。
Newtonsoft.Json 功能 | System.Text.Json equivalent |
---|---|
預設不區分大小寫的還原序列化 | ✔️ PropertyNameCaseInsensitive 全域設定 |
Camel 大小寫屬性名稱 | ✔️ PropertyNamingPolicy 全域設定 |
蛇案屬性名稱 | ✔️ 蛇案命名原則 |
最小字元逸出 | ✔️ 嚴格字元逸出,可設定 |
NullValueHandling.Ignore 全域設定 |
✔️ DefaultIgnoreCondition 全域選項 |
允許批註 | ✔️ ReadCommentHandling 全域設定 |
允許尾端逗號 | ✔️ AllowTrailingCommas 全域設定 |
自訂轉換器註冊 | ✔️ 優先順序順序不同 |
預設沒有最大深度 | ✔️ 預設最大深度 64,可設定 |
PreserveReferencesHandling 全域設定 |
✔️ ReferenceHandling 全域設定 |
以引號序列化或還原序列化數位 | ✔️ NumberHandling 全域設定 [JsonNumberHandling] 屬性 |
還原序列化為不可變的類別和結構 | ✔️ JsonConstructor、C# 9 記錄 |
欄位支援 | ✔️ IncludeFields 全域設定 [JsonInclude] 屬性 |
DefaultValueHandling 全域設定 |
✔️ DefaultIgnoreCondition 全域設定 |
NullValueHandling 設定開啟 [JsonProperty] |
✔️ JsonIgnore 屬性 |
DefaultValueHandling 設定開啟 [JsonProperty] |
✔️ JsonIgnore 屬性 |
使用非字串索引鍵還原序列化 Dictionary |
✔️ 支援 |
支援非公用屬性 setter 和 getter | ✔️ JsonInclude 屬性 |
[JsonConstructor] 屬性 |
✔️ [JsonConstructor] 屬性 |
ReferenceLoopHandling 全域設定 |
✔️ ReferenceHandling 全域設定 |
回撥 | ✔️ 回檔 |
NaN、Infinity、-Infinity | ✔️ 支援 |
Required 在屬性上 [JsonProperty] 設定 |
✔️ [JsonRequired] 屬性和 C# 必要修飾詞 |
DefaultContractResolver 忽略屬性 |
✔️ DefaultJsonTypeInfoResolver 類別 |
多型序列化 | ✔️ [JsonDerivedType] 屬性 |
多型還原序列化 | ✔️ [JsonDerivedType] 屬性上的類型歧視性 |
還原序列化字串列舉值 | ✔️ 還原序列化字串列舉值 |
MissingMemberHandling 全域設定 |
✔️ 處理遺漏的成員 |
在沒有 setter 的情況下填入屬性 | ✔️ 在沒有 setter 的情況下填入屬性 |
ObjectCreationHandling 全域設定 |
✔️ 重複使用而非取代屬性 |
支援廣泛的類型 | ⚠️ 某些類型需要自訂轉換器 |
將推斷的類型還原序列化為 object 屬性 |
⚠️ 不支援、因應措施、範例 |
將 JSON null 常值還原序列化為不可為 Null 的實數值型別 |
⚠️ 不支援、因應措施、範例 |
DateTimeZoneHandling 、 DateFormatString 設定 |
⚠️ 不支援、因應措施、範例 |
JsonConvert.PopulateObject 方法 |
⚠️ 不支援,因應措施 |
System.Runtime.Serialization 屬性的支援 |
⚠️ 不支援、因應措施、範例 |
JsonObjectAttribute |
⚠️ 不支援,因應措施 |
允許不含引號的屬性名稱 | ❌設計不支援 |
允許字串值周圍的單引號 | ❌設計不支援 |
允許字串屬性的非字串 JSON 值 | ❌設計不支援 |
TypeNameHandling.All 全域設定 |
❌設計不支援 |
JsonPath 查詢支援 |
❌不支援 |
可設定的限制 | ❌不支援 |
Newtonsoft.Json 功能 | System.Text.Json equivalent |
---|---|
預設不區分大小寫的還原序列化 | ✔️ PropertyNameCaseInsensitive 全域設定 |
Camel 大小寫屬性名稱 | ✔️ PropertyNamingPolicy 全域設定 |
最小字元逸出 | ✔️ 嚴格字元逸出,可設定 |
NullValueHandling.Ignore 全域設定 |
✔️ DefaultIgnoreCondition 全域選項 |
允許批註 | ✔️ ReadCommentHandling 全域設定 |
允許尾端逗號 | ✔️ AllowTrailingCommas 全域設定 |
自訂轉換器註冊 | ✔️ 優先順序順序不同 |
預設沒有最大深度 | ✔️ 預設最大深度 64,可設定 |
PreserveReferencesHandling 全域設定 |
✔️ ReferenceHandling 全域設定 |
以引號序列化或還原序列化數位 | ✔️ NumberHandling 全域設定 [JsonNumberHandling] 屬性 |
還原序列化為不可變的類別和結構 | ✔️ JsonConstructor、C# 9 記錄 |
欄位支援 | ✔️ IncludeFields 全域設定 [JsonInclude] 屬性 |
DefaultValueHandling 全域設定 |
✔️ DefaultIgnoreCondition 全域設定 |
NullValueHandling 設定開啟 [JsonProperty] |
✔️ JsonIgnore 屬性 |
DefaultValueHandling 設定開啟 [JsonProperty] |
✔️ JsonIgnore 屬性 |
使用非字串索引鍵還原序列化 Dictionary |
✔️ 支援 |
支援非公用屬性 setter 和 getter | ✔️ JsonInclude 屬性 |
[JsonConstructor] 屬性 |
✔️ [JsonConstructor] 屬性 |
ReferenceLoopHandling 全域設定 |
✔️ ReferenceHandling 全域設定 |
回撥 | ✔️ 回檔 |
NaN、Infinity、-Infinity | ✔️ 支援 |
Required 在屬性上 [JsonProperty] 設定 |
✔️ [JsonRequired] 屬性和 C# 必要修飾詞 |
DefaultContractResolver 忽略屬性 |
✔️ DefaultJsonTypeInfoResolver 類別 |
多型序列化 | ✔️ [JsonDerivedType] 屬性 |
多型還原序列化 | ✔️ [JsonDerivedType] 屬性上的類型歧視性 |
還原序列化字串列舉值 | ✔️ 還原序列化字串列舉值 |
支援廣泛的類型 | ⚠️ 某些類型需要自訂轉換器 |
將推斷的類型還原序列化為 object 屬性 |
⚠️ 不支援、因應措施、範例 |
將 JSON null 常值還原序列化為不可為 Null 的實數值型別 |
⚠️ 不支援、因應措施、範例 |
DateTimeZoneHandling 、 DateFormatString 設定 |
⚠️ 不支援、因應措施、範例 |
JsonConvert.PopulateObject 方法 |
⚠️ 不支援,因應措施 |
ObjectCreationHandling 全域設定 |
⚠️ 不支援,因應措施 |
新增至不含 setter 的集合 | ⚠️ 不支援,因應措施 |
蛇案屬性名稱 | ⚠️ 不支援,因應措施 |
System.Runtime.Serialization 屬性的支援 |
⚠️ 不支援、因應措施、範例 |
MissingMemberHandling 全域設定 |
⚠️ 不支援、因應措施、範例 |
JsonObjectAttribute |
⚠️ 不支援,因應措施 |
允許不含引號的屬性名稱 | ❌設計不支援 |
允許字串值周圍的單引號 | ❌設計不支援 |
允許字串屬性的非字串 JSON 值 | ❌設計不支援 |
TypeNameHandling.All 全域設定 |
❌設計不支援 |
JsonPath 查詢支援 |
❌不支援 |
可設定的限制 | ❌不支援 |
Newtonsoft.Json 功能 | System.Text.Json equivalent |
---|---|
預設不區分大小寫的還原序列化 | ✔️ PropertyNameCaseInsensitive 全域設定 |
Camel 大小寫屬性名稱 | ✔️ PropertyNamingPolicy 全域設定 |
最小字元逸出 | ✔️ 嚴格字元逸出,可設定 |
NullValueHandling.Ignore 全域設定 |
✔️ DefaultIgnoreCondition 全域選項 |
允許批註 | ✔️ ReadCommentHandling 全域設定 |
允許尾端逗號 | ✔️ AllowTrailingCommas 全域設定 |
自訂轉換器註冊 | ✔️ 優先順序順序不同 |
預設沒有最大深度 | ✔️ 預設最大深度 64,可設定 |
PreserveReferencesHandling 全域設定 |
✔️ ReferenceHandling 全域設定 |
以引號序列化或還原序列化數位 | ✔️ NumberHandling 全域設定 [JsonNumberHandling] 屬性 |
還原序列化為不可變的類別和結構 | ✔️ JsonConstructor、C# 9 記錄 |
欄位支援 | ✔️ IncludeFields 全域設定 [JsonInclude] 屬性 |
DefaultValueHandling 全域設定 |
✔️ DefaultIgnoreCondition 全域設定 |
NullValueHandling 設定開啟 [JsonProperty] |
✔️ JsonIgnore 屬性 |
DefaultValueHandling 設定開啟 [JsonProperty] |
✔️ JsonIgnore 屬性 |
使用非字串索引鍵還原序列化 Dictionary |
✔️ 支援 |
支援非公用屬性 setter 和 getter | ✔️ JsonInclude 屬性 |
[JsonConstructor] 屬性 |
✔️ [JsonConstructor] 屬性 |
ReferenceLoopHandling 全域設定 |
✔️ ReferenceHandling 全域設定 |
回撥 | ✔️ 回檔 |
NaN、Infinity、-Infinity | ✔️ 支援 |
還原序列化字串列舉值 | ✔️ 還原序列化字串列舉值 |
支援廣泛的類型 | ⚠️ 某些類型需要自訂轉換器 |
多型序列化 | ⚠️ 不支援、因應措施、範例 |
多型還原序列化 | ⚠️ 不支援、因應措施、範例 |
將推斷的類型還原序列化為 object 屬性 |
⚠️ 不支援、因應措施、範例 |
將 JSON null 常值還原序列化為不可為 Null 的實數值型別 |
⚠️ 不支援、因應措施、範例 |
Required 在屬性上 [JsonProperty] 設定 |
⚠️ 不支援、因應措施、範例 |
DefaultContractResolver 忽略屬性 |
⚠️ 不支援、因應措施、範例 |
DateTimeZoneHandling 、 DateFormatString 設定 |
⚠️ 不支援、因應措施、範例 |
JsonConvert.PopulateObject 方法 |
⚠️ 不支援,因應措施 |
ObjectCreationHandling 全域設定 |
⚠️ 不支援,因應措施 |
新增至不含 setter 的集合 | ⚠️ 不支援,因應措施 |
蛇案屬性名稱 | ⚠️ 不支援,因應措施 |
JsonObjectAttribute |
⚠️ 不支援,因應措施 |
System.Runtime.Serialization 屬性的支援 |
❌不支援 |
MissingMemberHandling 全域設定 |
❌不支援 |
允許不含引號的屬性名稱 | ❌設計不支援 |
允許字串值周圍的單引號 | ❌設計不支援 |
允許字串屬性的非字串 JSON 值 | ❌設計不支援 |
TypeNameHandling.All 全域設定 |
❌設計不支援 |
JsonPath 查詢支援 |
❌不支援 |
可設定的限制 | ❌不支援 |
這不是完整的功能清單 Newtonsoft.Json
。 此清單包含 GitHub 問題 或 StackOverflow 文章中 要求的許多案例。 如果您針對此處所列的其中一個案例實作因應措施,但目前沒有範例程式碼,而且如果您想要共用您的解決方案,請在此頁面底部的 [意見反應] 區段中選取 [此頁面 ]。 這會在此檔的 GitHub 存放庫中建立問題,並在此頁面的 [意見反應 ] 區段中列出此問題 。
預設行為的差異
System.Text.Json 預設為 strict,並避免呼叫端代表任何猜測或解譯,強調確定性行為。 程式庫是刻意設計為效能和安全性。 Newtonsoft.Json
預設為彈性。 這種設計的基本差異落後于下列許多預設行為的特定差異。
不區分大小寫的還原序列化
還原序列化期間, Newtonsoft.Json
預設會比對不區分大小寫的屬性名稱。 預設值 System.Text.Json 會區分大小寫,因為其執行完全相符,因此可提供更佳的效能。 如需如何執行不區分大小寫比對的詳細資訊,請參閱 不區分大小寫的屬性比對 。
如果您使用 ASP.NET Core 間接使用 System.Text.Json
,則不需要執行任何動作來取得類似 Newtonsoft.Json
的行為。 ASP.NET Core 會指定使用 System.Text.Json
時駱駝大小寫屬性名稱和不區分大小寫比對的設定。
ASP.NET Core 也預設會啟用還原序列化 引號數位 。
最小字元逸出
在序列化期間, Newtonsoft.Json
對於讓字元通過而不逸出字元相當寬鬆。 也就是說,它不會將它們 \uxxxx
xxxx
取代為 字元的程式碼點。 在逸出它們的位置,它會在字元之前發出 \
來執行此動作(例如, "
變成 \"
)。 System.Text.Json 預設會逸出更多字元,以針對跨網站腳本 (XSS) 或資訊洩漏攻擊提供深度防禦保護,並使用六個字元序列來執行此動作。 System.Text.Json
預設會逸出所有非 ASCII 字元,因此如果您在 中使用 StringEscapeHandling.EscapeNonAscii
Newtonsoft.Json
,就不需要執行任何動作。 System.Text.Json
也預設會逸出 HTML 敏感性字元。 如需如何覆寫預設 System.Text.Json
行為的資訊,請參閱 自訂字元編碼 。
註解
還原序列化期間, Newtonsoft.Json
預設會忽略 JSON 中的批註。 預設值 System.Text.Json 是擲回批註的例外狀況,因為 RFC 8259 規格不包含它們。 如需如何允許批註的資訊,請參閱 允許批註和尾端逗號 。
尾端逗號
還原序列化期間, Newtonsoft.Json
預設會忽略尾端逗號。 它也會忽略多個尾端逗號(例如 , [{"Color":"Red"},{"Color":"Green"},,]
。 預設值 System.Text.Json 是擲回尾端逗號的例外狀況,因為 RFC 8259 規格不允許它們。 如需如何接受 System.Text.Json
它們的資訊,請參閱 允許批註和尾端逗號 。 不允許多個尾端逗號。
轉換器註冊優先順序
Newtonsoft.Json
自訂轉換器的註冊優先順序如下:
- 屬性上的屬性
- 類型上的屬性
- Converters 集合
這個順序表示集合中的 Converters
自訂轉換器是由在類型層級套用屬性所註冊的轉換器覆寫。 這兩個註冊都會由屬性層級的屬性覆寫。
System.Text.Json自訂轉換器的註冊優先順序不同:
- 屬性上的屬性
- Converters 收集
- 類型上的屬性
這裡的差異在於集合中的 Converters
自訂轉換器會覆寫類型層級的屬性。 此優先順序背後的意圖是讓執行時間變更覆寫設計階段選擇。 無法變更優先順序。
如需自訂轉換器註冊的詳細資訊,請參閱 註冊自訂轉換器 。
最大深度
的最新版本 Newtonsoft.Json
預設最大深度限制為 64。 System.Text.Json 也有預設限制為 64,而且可藉由設定 JsonSerializerOptions.MaxDepth 來設定。
如果您使用 ASP.NET Core 間接使用 System.Text.Json
,預設的最大深度限制為 32。 預設值與模型系結相同,而且是在 JsonOptions 類別 中 設定。
JSON 字串 (屬性名稱和字串值)
還原序列化期間, Newtonsoft.Json
接受以雙引號、單引號或不含引號括住的屬性名稱。 它接受以雙引號或單引號括住的字串值。 例如, Newtonsoft.Json
接受下列 JSON:
{
"name1": "value",
'name2': "value",
name3: 'value'
}
System.Text.Json
只接受雙引號的屬性名稱和字串值,因為 RFC 8259 規格需要 該格式,而且是唯一被視為有效 JSON 的格式。
以單引號括住的值會產生 JsonException ,並顯示下列訊息:
''' is an invalid start of a value.
字串屬性的非字串值
Newtonsoft.Json
接受非字串值,例如數位或常值 true
和 false
,以便還原序列化為字串類型的屬性。 以下是成功還原序列化為下列類別的 JSON Newtonsoft.Json
範例:
{
"String1": 1,
"String2": true,
"String3": false
}
public class ExampleClass
{
public string String1 { get; set; }
public string String2 { get; set; }
public string String3 { get; set; }
}
System.Text.Json
不會將非字串值還原序列化為字串屬性。 針對字串欄位收到的非字串值會產生 JsonException ,並顯示下列訊息:
The JSON value could not be converted to System.String.
使用 JsonSerializer 的案例
內建功能不支援下列一些案例,但可能會有因應措施。 因應措施是 自訂轉換器 ,可能無法提供功能 Newtonsoft.Json
的完整同位。 針對其中一些,範例程式碼會以範例的形式提供。 如果您依賴這些功能 Newtonsoft.Json
,移轉將需要修改 .NET 物件模型或其他程式碼變更。
在下列某些案例中,因應措施並非實用或可能。 如果您依賴這些功能 Newtonsoft.Json
,則移轉將無法進行,而不會有重大變更。
允許或寫入引號中的數位
Newtonsoft.Json
可以序列化或還原序列化 JSON 字串所代表的數位(以引號括住)。 例如,它可以接受: {"DegreesCelsius":"23"}
而不是 {"DegreesCelsius":23}
。 若要在 中 System.Text.Json 啟用該行為,請將 設定 JsonSerializerOptions.NumberHandling 為 WriteAsString 或 AllowReadingFromString ,或使用 [JsonNumberHandling] 屬性。
如果您使用 ASP.NET Core 間接使用 System.Text.Json
,則不需要執行任何動作來取得類似 Newtonsoft.Json
的行為。 ASP.NET Core 會在 使用 System.Text.Json
時指定 Web 預設值 ,而 Web 預設值則允許加上引號的數位。
如需詳細資訊,請參閱 允許或寫入引號 中的數位。
指定還原序列化時要使用的建構函式
屬性 Newtonsoft.Json
[JsonConstructor]
可讓您指定要在還原序列化為 POCO 時呼叫的建構函式。
System.Text.Json
也有 [JsonConstructor] 屬性。 如需詳細資訊,請參閱 不可變的類型和記錄 。
有條件地忽略屬性
Newtonsoft.Json
有數種方式可以有條件地忽略序列化或還原序列化的屬性:
DefaultContractResolver
可讓您根據任意準則選取要包含或忽略的屬性。- 上的
NullValueHandling
JsonSerializerSettings
和DefaultValueHandling
設定可讓您指定應該忽略所有 Null 值或預設值屬性。 - 屬性
NullValueHandling
上的[JsonProperty]
和DefaultValueHandling
設定可讓您指定當設定為 null 或預設值時應該忽略的個別屬性。
System.Text.Json 提供下列在序列化時忽略屬性或欄位的方法:
- 屬性 上的 [JsonIgnore] 屬性會導致在序列化期間從 JSON 省略 屬性。
- IgnoreReadOnlyProperties 全域選項可讓您忽略所有唯讀屬性。
- 如果您 包含欄位 , JsonSerializerOptions.IgnoreReadOnlyFields 全域選項可讓您忽略所有唯讀欄位。
- 全域
DefaultIgnoreCondition
選項可讓您 忽略具有預設值的所有實數值型別屬性,或 忽略具有 Null 值 的所有參考型別屬性。
此外,在 .NET 7 和更新版本中,您可以自訂 JSON 合約,以根據任意準則忽略屬性。 如需詳細資訊,請參閱 自訂合約 。
這些選項 不會 讓您根據執行時間評估的任意準則來忽略選取的屬性。
公用和非公用欄位
Newtonsoft.Json
可以序列化和還原序列化欄位以及屬性。
在 System.Text.Json 中 JsonSerializerOptions.IncludeFields ,使用全域設定或 [JsonInclude] 屬性,在序列化或還原序列化時包含公用欄位。 如需範例,請參閱 包含欄位 。
保留物件參考和控制碼迴圈
根據預設, Newtonsoft.Json
依值序列化。 例如,如果物件包含兩個屬性,其中包含相同 Person
物件的參考,該 Person
物件的屬性值就會在 JSON 中重複。
Newtonsoft.Json
PreserveReferencesHandling
的 設定 JsonSerializerSettings
可讓您依參考序列化:
- 識別碼中繼資料會新增至為第一個
Person
物件建立的 JSON。 - 為第二
Person
個物件建立的 JSON 包含該識別碼的參考,而不是屬性值。
Newtonsoft.Json
也有一個 ReferenceLoopHandling
設定,可讓您忽略迴圈參考,而不是擲回例外狀況。
若要在 中 System.Text.Json 保留參考和處理迴圈參考,請將 設定 JsonSerializerOptions.ReferenceHandler 為 Preserve 。 此 ReferenceHandler.Preserve
設定相當於 PreserveReferencesHandling.All
PreserveReferencesHandling
= 中的 。 Newtonsoft.Json
選項 ReferenceHandler.IgnoreCycles
的行為類似于 Newtonsoft.JsonReferenceLoopHandling.Ignore
。 其中一個差異在於,實作會 System.Text.Json 以 JSON 權杖取代參考迴圈, null
而不是忽略物件參考。 如需詳細資訊,請參閱 忽略迴圈參考 。
Newtonsoft.Json 如同 ReferenceResolver ,類別 System.Text.Json.Serialization.ReferenceResolver 會定義在序列化和還原序列化上保留參考的行為。 建立衍生類別以指定自訂行為。 如需範例,請參閱 GuidReferenceResolver 。
不支援某些相關的 Newtonsoft.Json
功能:
如需詳細資訊,請參閱 保留參考和處理迴圈參考 。
具有非字串索引鍵的字典
和 都 Newtonsoft.Json
System.Text.Json
支援 類型的 Dictionary<TKey, TValue>
集合。 不過,在 中 System.Text.Json
TKey
,必須是基本類型,而不是自訂類型。 如需詳細資訊,請參閱 支援的金鑰類型 。
警告
還原序列化為 Dictionary<TKey, TValue>
TKey
類型為 以外的 string
任何專案,可能會造成取用應用程式中的安全性弱點。 如需詳細資訊,請參閱 dotnet/runtime#4761 。
沒有內建支援的類型
System.Text.Json 不提供下列類型的內建支援:
- DataTable 和相關類型 (如需詳細資訊,請參閱 支援的集合類型 )
- ExpandoObject
- TimeZoneInfo
- BigInteger
- DBNull
- Type
- ValueTuple 及其相關聯的泛型型別
針對沒有內建支援的類型,可以實作自訂轉換器。
多型序列化
Newtonsoft.Json
會自動進行多型序列化。 從 .NET 7 開始, System.Text.Json 支援透過 JsonDerivedTypeAttribute 屬性進行多型序列化。 如需詳細資訊,請參閱 序列化衍生類別 的屬性。
多型還原序列化
Newtonsoft.Json
具有在 TypeNameHandling
序列化時,將型別名稱中繼資料新增至 JSON 的設定。 它會在還原序列化時使用中繼資料來執行多型還原序列化。 從 .NET 7 開始, System.Text.Json 依賴型別歧視性資訊來執行多型還原序列化。 此中繼資料會在 JSON 中發出,然後在還原序列化期間用來判斷要還原序列化為基底類型或衍生型別。 如需詳細資訊,請參閱 序列化衍生類別 的屬性。
若要支援舊版 .NET 版本中的多型還原序列化,請在如何撰寫自訂轉換器中 建立類似範例的 轉換器。
還原序列化字串列舉值
根據預設, System.Text.Json 不支援還原序列化字串列舉值,而 Newtonsoft.Json
則支援。 例如,下列程式碼會 JsonException 擲回 :
string json = "{ \"Text\": \"Hello\", \"Enum\": \"Two\" }";
var _ = JsonSerializer.Deserialize<MyObj>(json); // Throws exception.
class MyObj
{
public string Text { get; set; } = "";
public MyEnum Enum { get; set; }
}
enum MyEnum
{
One,
Two,
Three
}
不過,您可以使用轉換器來啟用字串列舉值的 JsonStringEnumConverter 還原序列化。 如需詳細資訊,請參閱 列舉作為字串 。
還原序列化物件屬性
還原序列化為 Object 時 Newtonsoft.Json
,它會:
- 推斷 JSON 承載中基本值的類型(非
null
),並傳回儲存string
的 、long
、double
boolean
、 或DateTime
做為 Boxed 物件。 基本值是單一 JSON 值 ,例如 JSON 數位、字串、、false
true
或null
。 - 針對
JObject
JSON 承載中的複雜值傳回 或JArray
。 複雜值 是括弧內 JSON 索引鍵/值組的集合,{}
或括弧內的值清單([]
)。 大括弧或括弧內的屬性和值可以有額外的屬性或值。 - 當承載具有
null
JSON 常值時,傳回 Null 參考。
System.Text.Json每當還原序列化為 Object 時,會針對基本值和複雜值儲存 Boxed JsonElement
,例如:
object
屬性。object
字典值。object
陣列值。- 根
object
。
不過,當 null
承載中具有 null
JSON 常值時, System.Text.Json
會視為 相同的 Newtonsoft.Json
,並傳回 Null 參考。
若要實作 object
屬性的類型推斷,請建立轉換器,例如如何撰寫自訂轉換器 中的 範例。
將 Null 還原序列化為不可為 Null 的類型
Newtonsoft.Json
不會在下列案例中擲回例外狀況:
NullValueHandling
設定為Ignore
、 和- 還原序列化期間,JSON 包含不可為 Null 實數值型別的 Null 值。
在相同的案例中, System.Text.Json 會擲回例外狀況。 (中的 System.Text.Json
對應 Null 處理設定為 = JsonSerializerOptions.IgnoreNullValuestrue
。
如果您擁有目標型別,最佳因應措施是讓有問題的 屬性變成可為 Null(例如,變更 int
為 int?
)。
另一個因應措施是建立類型的轉換器,例如下列處理型別 Null 值的 DateTimeOffset
範例:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class DateTimeOffsetNullHandlingConverter : JsonConverter<DateTimeOffset>
{
public override DateTimeOffset Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
reader.TokenType == JsonTokenType.Null
? default
: reader.GetDateTimeOffset();
public override void Write(
Utf8JsonWriter writer,
DateTimeOffset dateTimeValue,
JsonSerializerOptions options) =>
writer.WriteStringValue(dateTimeValue);
}
}
在 屬性上使用 屬性或將轉換器 加入集合 Converters ,以註冊這個自訂轉換器 。
注意: 上述轉換器 會以不同于 Newtonsoft.Json
指定預設值的 POCO 來處理 Null 值。 例如,假設下列程式碼代表您的目標物件:
public class WeatherForecastWithDefault
{
public WeatherForecastWithDefault()
{
Date = DateTimeOffset.Parse("2001-01-01");
Summary = "No summary";
}
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string Summary { get; set; }
}
假設下列 JSON 是使用上述轉換器還原序列化:
{
"Date": null,
"TemperatureCelsius": 25,
"Summary": null
}
還原序列化之後, Date
屬性具有 1/1/0001 ( default(DateTimeOffset)
),也就是說,會覆寫建構函式中設定的值。 指定相同的 POCO 和 JSON, Newtonsoft.Json
還原序列化會在 屬性中 Date
保留 1/1/2001。
還原序列化為不可變的類別和結構
Newtonsoft.Json
可以還原序列化為不可變的類別和結構,因為它可以使用具有參數的建構函式。
在 System.Text.Json 中 ,使用 [JsonConstructor] 屬性來指定參數化建構函式的使用。 C# 9 中的記錄也是不可變的,而且支援做為還原序列化目標。 如需詳細資訊,請參閱 不可變的類型和記錄 。
必要屬性
在 中 Newtonsoft.Json
,您可以藉由在 屬性上 [JsonProperty]
設定 Required
來指定屬性。 Newtonsoft.Json
如果 JSON 中未收到標示為必要屬性的值,則會擲回例外狀況。
從 .NET 7 開始,您可以使用 C# required
修飾詞或 JsonRequiredAttribute 必要屬性上的 屬性。 System.Text.Json 如果 JSON 承載未包含標記屬性的值,則會擲回例外狀況。 如需詳細資訊,請參閱 必要屬性 。
System.Text.Json 如果未收到目標型別其中一個屬性的值,則不會擲回例外狀況。 例如,如果您有類別 WeatherForecast
:
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
下列 JSON 已還原序列化,而不會發生錯誤:
{
"TemperatureCelsius": 25,
"Summary": "Hot"
}
如果 JSON 中沒有任何 Date
屬性,若要使還原序列化失敗,請選擇下列其中一個選項:
- 使用 .NET 7 或更新版本的 System.Text.Json 套件 ,並將
required
修飾詞 (從 C# 11 開始提供)或 JsonRequiredAttribute 屬性新增至 屬性。 - 實作自訂轉換器。
- 實作回
OnDeserialized
呼 (.NET 6 和更新版本)。
如果還原序列化完成之後未設定 屬性, Date
下列範例轉換器程式碼會擲回例外狀況:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class WeatherForecastRequiredPropertyConverter : JsonConverter<WeatherForecast>
{
public override WeatherForecast Read(
ref Utf8JsonReader reader,
Type type,
JsonSerializerOptions options)
{
// Don't pass in options when recursively calling Deserialize.
WeatherForecast forecast = JsonSerializer.Deserialize<WeatherForecast>(ref reader)!;
// Check for required fields set by values in JSON
return forecast!.Date == default
? throw new JsonException("Required property not received in the JSON")
: forecast;
}
public override void Write(
Utf8JsonWriter writer,
WeatherForecast forecast, JsonSerializerOptions options)
{
// Don't pass in options when recursively calling Serialize.
JsonSerializer.Serialize(writer, forecast);
}
}
}
將 轉換器 新增至集合,以 JsonSerializerOptions.Converters 註冊此自訂轉換器。
以遞迴方式呼叫轉換器的這個模式需要您使用 來註冊轉換器 JsonSerializerOptions ,而不是使用 屬性。 如果您使用 屬性註冊轉換器,自訂轉換器會以遞迴方式呼叫本身。 結果是以堆疊溢位例外狀況結尾的無限迴圈。
當您使用 options 物件註冊轉換器時,在遞迴呼叫 Serialize 或 Deserialize 時,不要傳入 options 物件,以避免無限迴圈。 options 物件包含 Converters 集合。 如果您將它 Serialize
傳入 或 Deserialize
,則自訂轉換器會呼叫本身,並產生會導致堆疊溢位例外狀況的無限迴圈。 如果預設選項不可行,請使用您需要的設定建立選項的新實例。 由於每個新的實例都會獨立快取,因此此方法會變慢。
有一種替代模式可以使用 JsonConverterAttribute
要轉換之類別上的註冊。 在此方法中,轉換器程式碼會呼叫 Serialize
或 ,或 Deserialize
呼叫衍生自要轉換之類別的類別。 衍生類別未 JsonConverterAttribute
套用至該類別。 在此替代方法的下列範例中:
WeatherForecastWithRequiredPropertyConverterAttribute
是要還原序列化的類別,且已JsonConverterAttribute
套用至該類別。WeatherForecastWithoutRequiredPropertyConverterAttribute
是沒有轉換器屬性的衍生類別。- 轉換器中的程式碼會呼叫
Serialize
和Deserialize
開啟WeatherForecastWithoutRequiredPropertyConverterAttribute
,以避免無限迴圈。 由於額外的物件具現化和複製屬性值,此方法在序列化上會有效能成本。
以下是 WeatherForecast*
類型:
[JsonConverter(typeof(WeatherForecastRequiredPropertyConverterForAttributeRegistration))]
public class WeatherForecastWithRequiredPropertyConverterAttribute
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
public class WeatherForecastWithoutRequiredPropertyConverterAttribute :
WeatherForecastWithRequiredPropertyConverterAttribute
{
}
以下是轉換器:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class WeatherForecastRequiredPropertyConverterForAttributeRegistration :
JsonConverter<WeatherForecastWithRequiredPropertyConverterAttribute>
{
public override WeatherForecastWithRequiredPropertyConverterAttribute Read(
ref Utf8JsonReader reader,
Type type,
JsonSerializerOptions options)
{
// OK to pass in options when recursively calling Deserialize.
WeatherForecastWithRequiredPropertyConverterAttribute forecast =
JsonSerializer.Deserialize<WeatherForecastWithoutRequiredPropertyConverterAttribute>(
ref reader,
options)!;
// Check for required fields set by values in JSON.
return forecast!.Date == default
? throw new JsonException("Required property not received in the JSON")
: forecast;
}
public override void Write(
Utf8JsonWriter writer,
WeatherForecastWithRequiredPropertyConverterAttribute forecast,
JsonSerializerOptions options)
{
var weatherForecastWithoutConverterAttributeOnClass =
new WeatherForecastWithoutRequiredPropertyConverterAttribute
{
Date = forecast.Date,
TemperatureCelsius = forecast.TemperatureCelsius,
Summary = forecast.Summary
};
// OK to pass in options when recursively calling Serialize.
JsonSerializer.Serialize(
writer,
weatherForecastWithoutConverterAttributeOnClass,
options);
}
}
}
如果您需要處理 [JsonIgnore] 等 屬性或不同的選項,例如自訂編碼器,所需的屬性轉換器將需要額外的邏輯。 此外,範例程式碼不會處理建構函式中設定預設值的屬性。 此方法不會區分下列案例:
- JSON 中遺漏屬性。
- 不可為 Null 類型的屬性存在於 JSON 中,但值是型別的預設值,例如 的
int
零。 - 可為 Null 之實數值型別的屬性存在於 JSON 中,但值為 null。
注意
如果您是從 ASP.NET Core 控制器使用 System.Text.Json ,您可以在 [Required]
模型類別的屬性上使用 屬性,而不是實作 System.Text.Json 轉換器。
指定日期格式
Newtonsoft.Json
提供數種方式來控制 和 DateTimeOffset
型別的屬性 DateTime
序列化和還原序列化的方式:
- 此
DateTimeZoneHandling
設定可用來將所有值序列化DateTime
為 UTC 日期。 DateFormatString
設定和DateTime
轉換器可用來自訂日期字串的格式。
System.Text.Json 支援 ISO 8601-1:2019,包括 RFC 3339 設定檔。 這種格式被廣泛採用,明確,並精確地進行往返。 若要使用任何其他格式,請建立自訂轉換器。 例如,下列轉換器會序列化和還原序列化使用 Unix epoch 格式與時區位移或不含時區位移的 JSON(例如 /Date(1590863400000-0700)/
或 /Date(1590863400000)/
的值):
sealed class UnixEpochDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
static readonly DateTimeOffset s_epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
static readonly Regex s_regex = new Regex("^/Date\\(([+-]*\\d+)([+-])(\\d{2})(\\d{2})\\)/$", RegexOptions.CultureInvariant);
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
if (
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime)
|| !int.TryParse(match.Groups[3].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int hours)
|| !int.TryParse(match.Groups[4].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int minutes))
{
throw new JsonException();
}
int sign = match.Groups[2].Value[0] == '+' ? 1 : -1;
TimeSpan utcOffset = new TimeSpan(hours * sign, minutes * sign, 0);
return s_epoch.AddMilliseconds(unixTime).ToOffset(utcOffset);
}
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
TimeSpan utcOffset = value.Offset;
string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");
writer.WriteStringValue(formatted);
}
}
sealed class UnixEpochDateTimeConverter : JsonConverter<DateTime>
{
static readonly DateTime s_epoch = new DateTime(1970, 1, 1, 0, 0, 0);
static readonly Regex s_regex = new Regex("^/Date\\(([+-]*\\d+)\\)/$", RegexOptions.CultureInvariant);
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
if (
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime))
{
throw new JsonException();
}
return s_epoch.AddMilliseconds(unixTime);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime})/");
writer.WriteStringValue(formatted);
}
}
如需詳細資訊,請參閱 中的 System.Text.Json DateTime 和 DateTimeOffset 支援。
回撥
Newtonsoft.Json
可讓您在序列化或還原序列化程式中的數個點執行自訂程式碼:
- OnDeserializing (開始還原序列化物件時)
- OnDeserialized (完成還原序列化物件時)
- OnSerializing (開始序列化物件時)
- OnSerialized (完成序列化物件時)
System.Text.Json 會在序列化和還原序列化期間公開相同的通知。 若要使用它們,請從 命名空間實作 System.Text.Json.Serialization 下列一或多個介面:
以下範例會檢查 Null 屬性,並在序列化和還原序列化的開頭和結尾寫入訊息:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Callbacks
{
public class WeatherForecast :
IJsonOnDeserializing, IJsonOnDeserialized,
IJsonOnSerializing, IJsonOnSerialized
{
public DateTime Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
void IJsonOnDeserializing.OnDeserializing() => Console.WriteLine("\nBegin deserializing");
void IJsonOnDeserialized.OnDeserialized()
{
Validate();
Console.WriteLine("Finished deserializing");
}
void IJsonOnSerializing.OnSerializing()
{
Console.WriteLine("Begin serializing");
Validate();
}
void IJsonOnSerialized.OnSerialized() => Console.WriteLine("Finished serializing");
private void Validate()
{
if (Summary is null)
{
Console.WriteLine("The 'Summary' property is 'null'.");
}
}
}
public class Program
{
public static void Main()
{
var weatherForecast = new WeatherForecast
{
Date = DateTime.Parse("2019-08-01"),
TemperatureCelsius = 25,
};
string jsonString = JsonSerializer.Serialize(weatherForecast);
Console.WriteLine(jsonString);
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString);
Console.WriteLine($"Date={weatherForecast?.Date}");
Console.WriteLine($"TemperatureCelsius={weatherForecast?.TemperatureCelsius}");
Console.WriteLine($"Summary={weatherForecast?.Summary}");
}
}
}
// output:
//Begin serializing
//The 'Summary' property is 'null'.
//Finished serializing
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":null}
//Begin deserializing
//The 'Summary' property is 'null'.
//Finished deserializing
//Date=8/1/2019 12:00:00 AM
//TemperatureCelsius = 25
//Summary=
程式 OnDeserializing
代碼無法存取新的 POCO 實例。 若要在還原序列化開始時操作新的 POCO 實例,請將該程式碼放在 POCO 建構函式中。
非公用屬性 setter 和 getter
Newtonsoft.Json
可以透過 JsonProperty
屬性使用私用和內部屬性 setter 和 getter。
System.Text.Json透過 [JsonInclude] 屬性支援私用和內部屬性 setter 和 getter 。 如需範例程式碼,請參閱 非公用屬性存取子 。
填入現有的物件
中的 Newtonsoft.Json
方法會將 JsonConvert.PopulateObject
JSON 檔案還原序列化為類別的現有實例,而不是建立新的實例。 System.Text.Json 一律會使用預設的公用無參數建構函式,建立目標型別的新實例。 自訂轉換器可以還原序列化為現有的實例。
重複使用而非取代屬性
中的 ObjectCreationHandling
Newtonsoft.Json
設定可讓您指定屬性中的物件應該重複使用,而不是在還原序列化期間取代。 System.Text.Json 一律會取代屬性中的物件。 自訂轉換器可以提供這項功能,或者您可以升級至 .NET 8,以提供填入功能。
在沒有 setter 的情況下填入屬性
從 .NET 8 開始, System.Text.Json 支援填入屬性,包括沒有 setter 的屬性。 如需詳細資訊,請參閱 填入初始化的屬性 。
在還原序列化期間,即使 屬性沒有 setter, Newtonsoft.Json
也會將 物件加入至集合。 System.Text.Json 忽略沒有 setter 的屬性。 自訂轉換器可以提供這項功能,或者您可以升級至 .NET 8,以填入唯讀屬性。
蛇案命名原則
System.Text.Json 包含蛇案的內建命名原則。 不過,有些輸入的行為差異 Newtonsoft.Json
。 下表顯示使用 JsonNamingPolicy.SnakeCaseLower 原則轉換輸入時的其中一些差異。
輸入 | Newtonsoft.Json 結果 | System.Text.Json 結果 |
---|---|---|
「AB1」 | 「a_b1」 | 「ab1」 |
「SHA512Managed」 | 「sh_a512_managed」 | 「sha512_managed」 |
「abc123DEF456」 | 「abc123_de_f456」 | 「abc123_def456」 |
「KEBAB-CASE」 | 「keba_b-_case」 | 「kebab-case」 |
中 System.Text.Json 唯一的內建屬性命名原則是駱駝式大小寫。 Newtonsoft.Json
可以將屬性名稱轉換成蛇形大小寫。 自訂命名原則 可以提供這項功能,或升級至 .NET 8 或更新版本,其中包含內建蛇形案例命名原則。
System.Runtime.Serialization 屬性
System.Runtime.Serialization 屬性,例如 DataContractAttribute 、 DataMemberAttribute 和 IgnoreDataMemberAttribute 可讓您定義 資料合約 。 「 資料合約 」(Data Contract) 是服務與用戶端之間的正式合約,其中會抽象地描述要交換的資料。 資料合約會精確地定義要序列化哪些屬性以進行交換。
System.Text.Json 沒有這些屬性的內建支援。 不過,從 .NET 7 開始,您可以使用 自訂類型解析程式 來新增支援。 如需範例,請參閱 ZCS。DataContractResolver 。
八進位數位
Newtonsoft.Json
將前置零的數位視為八進位數。 System.Text.Json 不允許前置零,因為 RFC 8259 規格不允許它們。
處理遺漏的成員
如果要還原序列化的 JSON 包含目標型別中遺漏的屬性, Newtonsoft.Json
可以設定為擲回例外狀況。 根據預設, System.Text.Json 會忽略 JSON 中的額外屬性,但當您使用 [JsonExtensionData] 屬性 時除外。
在 .NET 8 和更新版本中,您可以使用下列其中一種方法來設定是否略過或不允許未對應的 JSON 屬性的喜好設定:
- 將 JsonUnmappedMemberHandlingAttribute 屬性套用至您要還原序列化的類型。
- 若要全域設定您的喜好設定,請設定 JsonSerializerOptions.UnmappedMemberHandling 屬性。 或者,針對來源產生,請設定 屬性, JsonSourceGenerationOptionsAttribute.UnmappedMemberHandling 並將 屬性套用至您的 JsonSerializerContext 類別。
- JsonTypeInfo.UnmappedMemberHandling自訂 屬性。
JsonObjectAttribute
Newtonsoft.Json
具有屬性 , JsonObjectAttribute
可在類型層級 套用 ,以控制哪些成員已序列化、 null
如何處理值,以及是否需要所有成員。 System.Text.Json 沒有可在類型上套用的對等屬性。 對於某些行為,例如 null
值處理,您可以在全域 JsonSerializerOptions 或每個屬性上個別設定相同的行為。
請考慮使用 來指定應忽略所有 null
屬性的下列範例 Newtonsoft.Json.JsonObjectAttribute
:
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class Person { ... }
在 中 System.Text.Json ,您可以設定所有類型和屬性 的行為 :
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
string json = JsonSerializer.Serialize<Person>(person, options);
或者,您可以個別 設定每個屬性的行為 :
public class Person
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Name { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? Age { get; set; }
}
接下來,請考慮下列用來 Newtonsoft.Json.JsonObjectAttribute
指定 JSON 中必須存在所有成員屬性的範例:
[JsonObject(ItemRequired = Required.Always)]
public class Person { ... }
您可以將 C# required
修飾詞或 JsonRequiredAttribute 新增至每個屬性 ,以達到相同的行為 System.Text.Json 。 如需詳細資訊,請參閱 必要屬性 。
public class Person
{
[JsonRequired]
public string? Name { get; set; }
public required int? Age { get; set; }
}
TraceWriter
Newtonsoft.Json
可讓您使用 TraceWriter
進行偵錯,以檢視序列化或還原序列化所產生的記錄。 System.Text.Json 不會進行記錄。
與 JToken 比較的 JsonDocument 和 JsonElement (例如 JObject、JArray)
System.Text.Json.JsonDocument 提供從現有 JSON 承載剖析和建 置唯讀 檔物件模型 (DOM) 的能力。 DOM 提供 JSON 承載中資料的隨機存取。 撰寫承載的 JSON 元素可以透過 JsonElement 類型存取。 此 JsonElement
類型提供 API,可將 JSON 文字轉換成一般 .NET 類型。 JsonDocument
RootElement會公開 屬性。
從 .NET 6 開始,您可以使用 命名空間中的 System.Text.Json.Nodes 類型和其他類型的,從現有的 JSON 承載 JsonNode 剖析和建 置可變 的 DOM。 如需詳細資訊,請參閱 使用 JsonNode
。
JsonDocument 是 IDisposable
JsonDocument
將資料的記憶體內部檢視建置到集區緩衝區中。 因此,與 或 JArray
JObject
不同 Newtonsoft.Json
, JsonDocument
型別會實作 IDisposable
,而且需要在 using 區塊內使用。 如需詳細資訊,請參閱 JsonDocument 是 IDisposable 。
JsonDocument 是唯讀的
System.Text.JsonDOM 無法新增、移除或修改 JSON 元素。 其設計方式適用于效能,並減少剖析常見 JSON 承載大小的配置(也就是 < 1 MB)。
JsonElement 是聯集結構
JsonDocument
會將 RootElement
公開 為 類型的 JsonElement 屬性,這是包含任何 JSON 元素的等位結構型別。 Newtonsoft.Json
會使用專用的階層類型,例如 JObject
、 JArray
、 JToken
等。 JsonElement
是您可以搜尋和列舉的內容,而且可用來 JsonElement
將 JSON 元素具體化為 .NET 類型。
從 .NET 6 開始,您可以在對應至 JObject
、 JArray
和 JToken
的 System.Text.Json.Nodes 命名空間中使用 JsonNode 類型和類型。 如需詳細資訊,請參閱 使用 JsonNode
。
如何搜尋 JsonDocument 和 JsonElement 以尋找子項目
使用 JObject
或 JArray
從 Newtonsoft.Json
搜尋 JSON 權杖通常比較快,因為它們在某些字典中是查閱。 相較之下,搜尋 JsonElement
需要循序搜尋屬性,因此相對緩慢(例如使用 TryGetProperty
時)。 System.Text.Json 是設計來將初始剖析時間降到最低,而不是查閱時間。 如需詳細資訊,請參閱 如何搜尋 JsonDocument 和 JsonElement 以取得子項目 。
與 JsonTextReader 比較的 Utf8JsonReader
System.Text.Json.Utf8JsonReader是 UTF-8 編碼 JSON 文字的高效能、低配置、僅限轉送讀取器、從 ReadOnlySpan < 位元組 > 或 ReadOnlySequence < 位元組 > 讀取。 Utf8JsonReader
是一種低階類型,可用來建置自訂剖析器和還原序列化器。
Utf8JsonReader 是 ref 結構
中的 JsonTextReader
Newtonsoft.Json
是類別。 類型 Utf8JsonReader
的差異在於它是 ref 結構 。 如需詳細資訊,請參閱 utf8JsonReader 的 ref 結構限制。
將 Null 值讀入可為 Null 的實數值型別
Newtonsoft.Json
提供可傳回 Nullable<T> 的 API,例如 ReadAsBoolean
,其會藉由傳回 bool?
來為您處理 Null
TokenType
。 內 System.Text.Json
建 API 只會傳回不可為 Null 的實值型別。 如需詳細資訊,請參閱 將 Null 值讀入可為 Null 的實數值型別 。
多目標
如果您需要繼續使用 Newtonsoft.Json
特定目標架構,您可以多目標並有兩個實作。 不過,這並不簡單,而且需要一些 #ifdefs
和來源重複。 盡可能共用程式碼的其中一 ref struct
種方式是建立 和 Newtonsoft.Json
JsonTextReader
的 Utf8JsonReader
包裝函式。 此包裝函式會統一公用介面區,同時隔離行為差異。 這可讓您將變更主要隔離至型別的建構,並藉由參考傳遞新的型別。 這是 Microsoft.Extensions.DependencyModel 程式庫遵循的 模式:
相較于 JsonTextWriter,Utf8JsonWriter
System.Text.Json.Utf8JsonWriter是從 、 Int32
、 和 DateTime
等 String
常見 .NET 類型寫入 UTF-8 編碼 JSON 文字的高效能方式。 寫入器是一種低階類型,可用來建置自訂序列化程式。
撰寫原始值
方法 Newtonsoft.Json
WriteRawValue
會寫入預期的原始 JSON。 System.Text.Json 具有直接對等專案: Utf8JsonWriter.WriteRawValue 。 如需詳細資訊,請參閱 撰寫原始 JSON 。
自訂 JSON 格式
JsonTextWriter
包含下列沒有對等的設定 Utf8JsonWriter
:
- 縮排 - 指定要縮排 的字元數。
Utf8JsonWriter
一律縮排 2 個字元。 - IndentChar - 指定要用於縮排的字元。
Utf8JsonWriter
一律使用空白字元。 - QuoteChar - 指定要用來括住字串值的字元。
Utf8JsonWriter
一律使用雙引號。 - QuoteName - 指定是否要以引號括住屬性名稱。
Utf8JsonWriter
一律以引號括住它們。
沒有任何因應措施可讓您以這些方式自訂 所產生的 Utf8JsonWriter
JSON。
寫入 Timespan、Uri 或 char 值
JsonTextWriter
提供 WriteValue
TimeSpan 、 Uri 和 char 值的方法 。 Utf8JsonWriter
沒有對等的方法。 相反地,請將這些值格式化為字串(例如呼叫 ToString()
,例如)並呼叫 WriteStringValue 。
多目標
如果您需要繼續使用 Newtonsoft.Json
特定目標架構,您可以多目標並有兩個實作。 不過,這並不簡單,而且需要一些 #ifdefs
和來源重複。 盡可能共用程式碼的其中一種方式是建立 和 Newtonsoft
JsonTextWriter
的 Utf8JsonWriter
包裝函式。 此包裝函式會統一公用介面區,同時隔離行為差異。 這可讓您主要隔離類型建構的變更。 Microsoft.Extensions.DependencyModel 程式庫如下:
TypeNameHandling.All 不支援
從 中排除 TypeNameHandling.All
對等功能 System.Text.Json
的決定是刻意的。 允許 JSON 承載指定自己的類型資訊,是 Web 應用程式中常見的弱點來源。 特別是,使用 設定 Newtonsoft.Json
TypeNameHandling.All
可讓遠端用戶端在 JSON 承載本身內嵌整個可執行應用程式,以便在還原序列化期間,Web 應用程式擷取並執行內嵌程式碼。 如需詳細資訊,請參閱 星期五第 13 次 JSON 攻擊 PowerPoint 和 星期五第 13 個 JSON 攻擊詳細資料 。
不支援 JSON 路徑查詢
JsonDocument
DOM 不支援使用 JSON 路徑 進行查詢。
JsonNode在 DOM 中,每個 JsonNode
實例都有一個 GetPath
方法可傳回該節點的路徑。 但是沒有內建的 API 會根據 JSON 路徑查詢字串來處理查詢。
如需詳細資訊,請參閱 dotnet/runtime #31068 GitHub 問題 。
某些限制無法設定
System.Text.Json 會設定某些值無法變更的限制,例如字元大小上限(166 MB)和基底 64(125 MB)。 如需詳細資訊,請參閱 JsonConstants
原始程式碼 和 GitHub 問題 dotnet/runtime #39953 。
NaN、Infinity、-Infinity
Newtonsoft 會 NaN
剖析 、 Infinity
和 -Infinity
JSON 字串權杖。 搭配 System.Text.Json 使用 ,請使用 JsonNumberHandling.AllowNamedFloatingPointLiterals 。 如需如何使用此設定的資訊,請參閱 允許或寫入引號 中的數位。
其他資源
意見反應
提交並檢視相關的意見反應