如何在 System.Text.Json 中使用 Utf8JsonWriter
本文說明如何使用 Utf8JsonWriter 類型來建置自訂序列化程式。
Utf8JsonWriter 是一種高效能方式,可從常見的 .NET 類型 (例如 String
、Int32
與 DateTime
) 撰寫 UTF-8 編碼的 JSON 文字。 寫入器是一個低階類型,可用於建置自訂序列化程式。 實際上,JsonSerializer.Serialize 方法會使用 Utf8JsonWriter
。
下列範例將示範如何使用 Utf8JsonWriter 類別:
var options = new JsonWriterOptions
{
Indented = true
};
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, options);
writer.WriteStartObject();
writer.WriteString("date", DateTimeOffset.UtcNow);
writer.WriteNumber("temp", 42);
writer.WriteEndObject();
writer.Flush();
string json = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(json);
Dim options As JsonWriterOptions = New JsonWriterOptions With {
.Indented = True
}
Dim stream As MemoryStream = New MemoryStream
Dim writer As Utf8JsonWriter = New Utf8JsonWriter(stream, options)
writer.WriteStartObject()
writer.WriteString("date", DateTimeOffset.UtcNow)
writer.WriteNumber("temp", 42)
writer.WriteEndObject()
writer.Flush()
Dim json As String = Encoding.UTF8.GetString(stream.ToArray())
Console.WriteLine(json)
使用 UTF-8 文字撰寫
若要在使用 Utf8JsonWriter
時達到最佳效能,請撰寫已編碼為 UTF-8 文字的 JSON 承載,而非 UTF-16 字串。 使用 JsonEncodedText 快取並預先編碼已知的字串屬性名稱和值作為靜態,並將這些名稱和值傳遞至寫入器,而非使用 UTF-16 字串常值。 這比快取和使用 UTF-8 位元組陣列更快。
如果您需要執行自訂逸出,此方法也適用。 System.Text.Json
不會讓您在撰寫字串時停用逸出。 不過,您可以將自己的自訂 JavaScriptEncoder 作為選項傳遞至寫入器,或建立自己的 JsonEncodedText
,以使用您的 JavascriptEncoder
來執行逸出,然後寫入 JsonEncodedText
而非字串。 如需詳細資訊,請參閱自訂字元編碼。
撰寫原始 JSON
在某些情況下,您可能會想要將「原始」JSON 寫入您正在使用 Utf8JsonWriter
建立的 JSON 承載。 您可以使用 Utf8JsonWriter.WriteRawValue 來執行此作業。 以下是典型案例:
您有想要以新 JSON 括住的現有 JSON 承載。
您想要將值設定為不同於預設
Utf8JsonWriter
格式設定的格式。例如,您可能想要自訂數字格式設定。 根據預設,System.Text.Json 會省略整數的小數點;例如,寫入
1
而非1.0
。 其理由是寫入較少的位元組有益效能。 但假設 JSON 的取用者會將具有小數的數字視為雙精度浮點數,而不含小數點的數字則視為整數。 建議您藉由撰寫整數的小數點和零,確保陣列中的數字全都辨識為雙精度浮點數。 下列範例顯示如何執行該項工作:using System.Text; using System.Text.Json; namespace WriteRawJson; public class Program { public static void Main() { JsonWriterOptions writerOptions = new() { Indented = true, }; using MemoryStream stream = new(); using Utf8JsonWriter writer = new(stream, writerOptions); writer.WriteStartObject(); writer.WriteStartArray("defaultJsonFormatting"); foreach (double number in new double[] { 50.4, 51 }) { writer.WriteStartObject(); writer.WritePropertyName("value"); writer.WriteNumberValue(number); writer.WriteEndObject(); } writer.WriteEndArray(); writer.WriteStartArray("customJsonFormatting"); foreach (double result in new double[] { 50.4, 51 }) { writer.WriteStartObject(); writer.WritePropertyName("value"); writer.WriteRawValue( FormatNumberValue(result), skipInputValidation: true); writer.WriteEndObject(); } writer.WriteEndArray(); writer.WriteEndObject(); writer.Flush(); string json = Encoding.UTF8.GetString(stream.ToArray()); Console.WriteLine(json); } static string FormatNumberValue(double numberValue) { return numberValue == Convert.ToInt32(numberValue) ? numberValue.ToString() + ".0" : numberValue.ToString(); } } // output: //{ // "defaultJsonFormatting": [ // { // "value": 50.4 // }, // { // "value": 51 // } // ], // "customJsonFormatting": [ // { // "value": 50.4 // }, // { // "value": 51.0 // } // ] //}
自訂字元逸出
JsonTextWriter
的 StringEscapeHandling 設定提供逸出所有非 ASCII 字元或 HTML 字元的選項。 根據預設,Utf8JsonWriter
會逸出所有非 ASCII 和 HTML 字元。 此逸出是為了深層防禦安全性理由而進行的。 若要指定不同的逸出原則,請建立 JavaScriptEncoder 並設定 JsonWriterOptions.Encoder。 如需詳細資訊,請參閱自訂字元編碼。
撰寫 null 值
若要使用 Utf8JsonWriter
撰寫 null 值,請呼叫:
- WriteNull 以將機碼值組寫入 null 作為值。
- WriteNullValue 以將 null 寫入為 JSON 陣列的元素。
針對字串屬性,如果字串為 null,則 WriteString 和 WriteStringValue 相當於 WriteNull
和 WriteNullValue
。
撰寫 Timespan、URI 或 char 值
若要撰寫 Timespan
、Uri
、或 char
值,請將其格式化為字串 (例如藉由呼叫 ToString()
) 並呼叫 WriteStringValue。