從 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 的實數值型別 ⚠️ 不支援、因應措施、範例
DateTimeZoneHandlingDateFormatString 設定 ⚠️ 不支援、因應措施、範例
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 的實數值型別 ⚠️ 不支援、因應措施、範例
DateTimeZoneHandlingDateFormatString 設定 ⚠️ 不支援、因應措施、範例
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 忽略屬性 ⚠️ 不支援、因應措施、範例
DateTimeZoneHandlingDateFormatString 設定 ⚠️ 不支援、因應措施、範例
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 對於讓字元通過而不逸出字元相當寬鬆。 也就是說,它不會將它們 \uxxxxxxxx 取代為 字元的程式碼點。 在逸出它們的位置,它會在字元之前發出 \ 來執行此動作(例如, " 變成 \" )。 System.Text.Json 預設會逸出更多字元,以針對跨網站腳本 (XSS) 或資訊洩漏攻擊提供深度防禦保護,並使用六個字元序列來執行此動作。 System.Text.Json 預設會逸出所有非 ASCII 字元,因此如果您在 中使用 StringEscapeHandling.EscapeNonAsciiNewtonsoft.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 接受非字串值,例如數位或常值 truefalse ,以便還原序列化為字串類型的屬性。 以下是成功還原序列化為下列類別的 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.NumberHandlingWriteAsStringAllowReadingFromString ,或使用 [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 可讓您根據任意準則選取要包含或忽略的屬性。
  • 上的 NullValueHandlingJsonSerializerSettingsDefaultValueHandling 設定可讓您指定應該忽略所有 Null 值或預設值屬性。
  • 屬性 NullValueHandling 上的 [JsonProperty]DefaultValueHandling 設定可讓您指定當設定為 null 或預設值時應該忽略的個別屬性。

System.Text.Json 提供下列在序列化時忽略屬性或欄位的方法:

此外,在 .NET 7 和更新版本中,您可以自訂 JSON 合約,以根據任意準則忽略屬性。 如需詳細資訊,請參閱 自訂合約

這些選項 不會 讓您根據執行時間評估的任意準則來忽略選取的屬性。

公用和非公用欄位

Newtonsoft.Json 可以序列化和還原序列化欄位以及屬性。

System.Text.JsonJsonSerializerOptions.IncludeFields ,使用全域設定或 [JsonInclude] 屬性,在序列化或還原序列化時包含公用欄位。 如需範例,請參閱 包含欄位

保留物件參考和控制碼迴圈

根據預設, Newtonsoft.Json 依值序列化。 例如,如果物件包含兩個屬性,其中包含相同 Person 物件的參考,該 Person 物件的屬性值就會在 JSON 中重複。

Newtonsoft.JsonPreserveReferencesHandling的 設定 JsonSerializerSettings 可讓您依參考序列化:

  • 識別碼中繼資料會新增至為第一個 Person 物件建立的 JSON。
  • 為第二 Person 個物件建立的 JSON 包含該識別碼的參考,而不是屬性值。

Newtonsoft.Json 也有一個 ReferenceLoopHandling 設定,可讓您忽略迴圈參考,而不是擲回例外狀況。

若要在 中 System.Text.Json 保留參考和處理迴圈參考,請將 設定 JsonSerializerOptions.ReferenceHandlerPreserve 。 此 ReferenceHandler.Preserve 設定相當於 PreserveReferencesHandling.AllPreserveReferencesHandling = 中的 。 Newtonsoft.Json

選項 ReferenceHandler.IgnoreCycles 的行為類似于 Newtonsoft.JsonReferenceLoopHandling.Ignore 。 其中一個差異在於,實作會 System.Text.Json 以 JSON 權杖取代參考迴圈, null 而不是忽略物件參考。 如需詳細資訊,請參閱 忽略迴圈參考

Newtonsoft.Json 如同 ReferenceResolver ,類別 System.Text.Json.Serialization.ReferenceResolver 會定義在序列化和還原序列化上保留參考的行為。 建立衍生類別以指定自訂行為。 如需範例,請參閱 GuidReferenceResolver

不支援某些相關的 Newtonsoft.Json 功能:

如需詳細資訊,請參閱 保留參考和處理迴圈參考

具有非字串索引鍵的字典

和 都 Newtonsoft.JsonSystem.Text.Json 支援 類型的 Dictionary<TKey, TValue> 集合。 不過,在 中 System.Text.JsonTKey ,必須是基本類型,而不是自訂類型。 如需詳細資訊,請參閱 支援的金鑰類型

警告

還原序列化為 Dictionary<TKey, TValue>TKey 類型為 以外的 string 任何專案,可能會造成取用應用程式中的安全性弱點。 如需詳細資訊,請參閱 dotnet/runtime#4761

沒有內建支援的類型

System.Text.Json 不提供下列類型的內建支援:

針對沒有內建支援的類型,可以實作自訂轉換器。

多型序列化

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 還原序列化。 如需詳細資訊,請參閱 列舉作為字串

還原序列化物件屬性

還原序列化為 ObjectNewtonsoft.Json ,它會:

  • 推斷 JSON 承載中基本值的類型(非 null ),並傳回儲存 string 的 、 longdoubleboolean 、 或 DateTime 做為 Boxed 物件。 基本值是單一 JSON 值 ,例如 JSON 數位、字串、、 falsetruenull
  • 針對 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(例如,變更 intint? )。

另一個因應措施是建立類型的轉換器,例如下列處理型別 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 屬性,若要使還原序列化失敗,請選擇下列其中一個選項:

如果還原序列化完成之後未設定 屬性, 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 物件註冊轉換器時,在遞迴呼叫 SerializeDeserialize 時,不要傳入 options 物件,以避免無限迴圈。 options 物件包含 Converters 集合。 如果您將它 Serialize 傳入 或 Deserialize ,則自訂轉換器會呼叫本身,並產生會導致堆疊溢位例外狀況的無限迴圈。 如果預設選項不可行,請使用您需要的設定建立選項的新實例。 由於每個新的實例都會獨立快取,因此此方法會變慢。

有一種替代模式可以使用 JsonConverterAttribute 要轉換之類別上的註冊。 在此方法中,轉換器程式碼會呼叫 Serialize 或 ,或 Deserialize 呼叫衍生自要轉換之類別的類別。 衍生類別未 JsonConverterAttribute 套用至該類別。 在此替代方法的下列範例中:

  • WeatherForecastWithRequiredPropertyConverterAttribute 是要還原序列化的類別,且已 JsonConverterAttribute 套用至該類別。
  • WeatherForecastWithoutRequiredPropertyConverterAttribute 是沒有轉換器屬性的衍生類別。
  • 轉換器中的程式碼會呼叫 SerializeDeserialize 開啟 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 一律會使用預設的公用無參數建構函式,建立目標型別的新實例。 自訂轉換器可以還原序列化為現有的實例。

重複使用而非取代屬性

從 .NET 8 開始, System.Text.Json 支援重複使用初始化的屬性,而不是取代它們。 行為有一些差異,您可以在 API 提案 閱讀。

如需詳細資訊,請參閱 填入初始化的屬性

中的 ObjectCreationHandlingNewtonsoft.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 屬性,例如 DataContractAttributeDataMemberAttributeIgnoreDataMemberAttribute 可讓您定義 資料合約 。 「 資料合約 」(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 屬性的喜好設定:

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 類型。 JsonDocumentRootElement會公開 屬性。

從 .NET 6 開始,您可以使用 命名空間中的 System.Text.Json.Nodes 類型和其他類型的,從現有的 JSON 承載 JsonNode 剖析和建 置可變 的 DOM。 如需詳細資訊,請參閱 使用 JsonNode

JsonDocument 是 IDisposable

JsonDocument 將資料的記憶體內部檢視建置到集區緩衝區中。 因此,與 或 JArrayJObject 不同 Newtonsoft.JsonJsonDocument 型別會實作 IDisposable ,而且需要在 using 區塊內使用。 如需詳細資訊,請參閱 JsonDocument 是 IDisposable

JsonDocument 是唯讀的

System.Text.JsonDOM 無法新增、移除或修改 JSON 元素。 其設計方式適用于效能,並減少剖析常見 JSON 承載大小的配置(也就是 < 1 MB)。

JsonElement 是聯集結構

JsonDocument 會將 RootElement 公開 為 類型的 JsonElement 屬性,這是包含任何 JSON 元素的等位結構型別。 Newtonsoft.Json 會使用專用的階層類型,例如 JObjectJArrayJToken 等。 JsonElement 是您可以搜尋和列舉的內容,而且可用來 JsonElement 將 JSON 元素具體化為 .NET 類型。

從 .NET 6 開始,您可以在對應至 JObjectJArrayJTokenSystem.Text.Json.Nodes 命名空間中使用 JsonNode 類型和類型。 如需詳細資訊,請參閱 使用 JsonNode

如何搜尋 JsonDocument 和 JsonElement 以尋找子項目

使用 JObjectJArrayNewtonsoft.Json 搜尋 JSON 權杖通常比較快,因為它們在某些字典中是查閱。 相較之下,搜尋 JsonElement 需要循序搜尋屬性,因此相對緩慢(例如使用 TryGetProperty 時)。 System.Text.Json 是設計來將初始剖析時間降到最低,而不是查閱時間。 如需詳細資訊,請參閱 如何搜尋 JsonDocument 和 JsonElement 以取得子項目

與 JsonTextReader 比較的 Utf8JsonReader

System.Text.Json.Utf8JsonReader是 UTF-8 編碼 JSON 文字的高效能、低配置、僅限轉送讀取器、從 ReadOnlySpan < 位元組 > 或 ReadOnlySequence < 位元組 > 讀取。 Utf8JsonReader是一種低階類型,可用來建置自訂剖析器和還原序列化器。

Utf8JsonReader 是 ref 結構

中的 JsonTextReaderNewtonsoft.Json 是類別。 類型 Utf8JsonReader 的差異在於它是 ref 結構 。 如需詳細資訊,請參閱 utf8JsonReader 的 ref 結構限制。

將 Null 值讀入可為 Null 的實數值型別

Newtonsoft.Json提供可傳回 Nullable<T> 的 API,例如 ReadAsBoolean ,其會藉由傳回 bool? 來為您處理 NullTokenType 。 內 System.Text.Json 建 API 只會傳回不可為 Null 的實值型別。 如需詳細資訊,請參閱 將 Null 值讀入可為 Null 的實數值型別

多目標

如果您需要繼續使用 Newtonsoft.Json 特定目標架構,您可以多目標並有兩個實作。 不過,這並不簡單,而且需要一些 #ifdefs 和來源重複。 盡可能共用程式碼的其中一 ref struct 種方式是建立 和 Newtonsoft.JsonJsonTextReaderUtf8JsonReader 包裝函式。 此包裝函式會統一公用介面區,同時隔離行為差異。 這可讓您將變更主要隔離至型別的建構,並藉由參考傳遞新的型別。 這是 Microsoft.Extensions.DependencyModel 程式庫遵循的 模式:

相較于 JsonTextWriter,Utf8JsonWriter

System.Text.Json.Utf8JsonWriter是從 、 Int32 、 和 DateTimeString 常見 .NET 類型寫入 UTF-8 編碼 JSON 文字的高效能方式。 寫入器是一種低階類型,可用來建置自訂序列化程式。

撰寫原始值

方法 Newtonsoft.JsonWriteRawValue 會寫入預期的原始 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 和來源重複。 盡可能共用程式碼的其中一種方式是建立 和 NewtonsoftJsonTextWriterUtf8JsonWriter 包裝函式。 此包裝函式會統一公用介面區,同時隔離行為差異。 這可讓您主要隔離類型建構的變更。 Microsoft.Extensions.DependencyModel 程式庫如下:

TypeNameHandling.All 不支援

從 中排除 TypeNameHandling.All 對等功能 System.Text.Json 的決定是刻意的。 允許 JSON 承載指定自己的類型資訊,是 Web 應用程式中常見的弱點來源。 特別是,使用 設定 Newtonsoft.JsonTypeNameHandling.All 可讓遠端用戶端在 JSON 承載本身內嵌整個可執行應用程式,以便在還原序列化期間,Web 應用程式擷取並執行內嵌程式碼。 如需詳細資訊,請參閱 星期五第 13 次 JSON 攻擊 PowerPoint 星期五第 13 個 JSON 攻擊詳細資料

不支援 JSON 路徑查詢

JsonDocumentDOM 不支援使用 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 。 如需如何使用此設定的資訊,請參閱 允許或寫入引號 中的數位。

其他資源