.NET 中的 JSON 序列化和反序列化(封送和拆收)- 概述
System.Text.Json 命名空间提供用于序列化和反序列化 JavaScript 对象表示法 (JSON) 的功能。 序列化是将对象状态(即其属性的值)转换为可存储或传输的形式的过程。 序列化形式不包含有关对象的关联方法的任何信息。 反序列化从序列化形式重新构造对象。
System.Text.Json
库的设计强调对广泛的功能集实现高性能和低内存分配。 内置的 UTF-8 支持可优化读写以 UTF-8 编码的 JSON 文本的过程,UTF-8 编码是针对 Web 上的数据和磁盘上的文件的最普遍的编码方式。
库还提供了用于处理内存中文档对象模型 (DOM) 的类。 此功能允许对 JSON 文件或字符串中的元素进行随机访问。
对于 Visual Basic,可以使用的库部分有一些相关限制。 有关详细信息,请参阅 Visual Basic 支持。
如何获取库
该库是作为 .NET Core 3.0 及更高版本共享框架的一部分内置的。 源生成功能内置在 .NET 6 和更高版本的共享框架中。
对于早于 .NET Core 3.0 的框架版本,请安装 System.Text.Json NuGet 包。 包支持以下框架:
- .NET Standard 2.0 及更高版本
- .NET Framework 4.6.2 及更高版本
- .NET Core 2.1 及更高版本
- .NET 5 及更高版本
命名空间和 API
- System.Text.Json 命名空间包含所有入口点和主要类型。
- System.Text.Json.Serialization 命名空间包含用于高级方案的特性和 API,以及特定于序列化和反序列化的自定义。
本文中演示的代码示例要求将 using
指令用于其中一个或两个命名空间。
重要
System.Text.Json
不支持以前可能使用过的以下序列化 API:
- System.Runtime.Serialization 命名空间中的属性。
- System.SerializableAttribute 属性和 ISerializable 接口。 这些类型仅用于二进制和 XML 序列化。
HttpClient 和 HttpContent 扩展方法
序列化和反序列化来自网络的 JSON 有效负载是常见的操作。 HttpClient 和 HttpContent 上的扩展方法允许在单个代码行中执行这些操作。 这些扩展方法使用 JsonSerializerOptions 的 Web 默认值。
以下示例说明了 HttpClientJsonExtensions.GetFromJsonAsync 和 HttpClientJsonExtensions.PostAsJsonAsync 的用法:
using System.Net.Http.Json;
namespace HttpClientExtensionMethods
{
public class User
{
public int Id { get; set; }
public string? Name { get; set; }
public string? Username { get; set; }
public string? Email { get; set; }
}
public class Program
{
public static async Task Main()
{
using HttpClient client = new()
{
BaseAddress = new Uri("https://jsonplaceholder.typicode.com")
};
// Get the user information.
User? user = await client.GetFromJsonAsync<User>("users/1");
Console.WriteLine($"Id: {user?.Id}");
Console.WriteLine($"Name: {user?.Name}");
Console.WriteLine($"Username: {user?.Username}");
Console.WriteLine($"Email: {user?.Email}");
// Post a new user.
HttpResponseMessage response = await client.PostAsJsonAsync("users", user);
Console.WriteLine(
$"{(response.IsSuccessStatusCode ? "Success" : "Error")} - {response.StatusCode}");
}
}
}
// Produces output like the following example but with different names:
//
//Id: 1
//Name: Tyler King
//Username: Tyler
//Email: Tyler@contoso.com
//Success - Created
Imports System.Net.Http
Imports System.Net.Http.Json
Namespace HttpClientExtensionMethods
Public Class User
Public Property Id As Integer
Public Property Name As String
Public Property Username As String
Public Property Email As String
End Class
Public Class Program
Public Shared Async Function Main() As Task
Using client As New HttpClient With {
.BaseAddress = New Uri("https://jsonplaceholder.typicode.com")
}
' Get the user information.
Dim user1 As User = Await client.GetFromJsonAsync(Of User)("users/1")
Console.WriteLine($"Id: {user1.Id}")
Console.WriteLine($"Name: {user1.Name}")
Console.WriteLine($"Username: {user1.Username}")
Console.WriteLine($"Email: {user1.Email}")
' Post a new user.
Dim response As HttpResponseMessage = Await client.PostAsJsonAsync("users", user1)
Console.WriteLine(
$"{(If(response.IsSuccessStatusCode, "Success", "Error"))} - {response.StatusCode}")
End Using
End Function
End Class
End Namespace
' Produces output like the following example but with different names:
'
'Id: 1
'Name: Tyler King
'Username: Tyler
'Email: Tyler@contoso.com
'Success - Created
此外还有 System.Text.Json 上的 System.Text.Json 的扩展方法。
反射与源生成
默认情况下,System.Text.Json
使用反射来收集所需的元数据,用于在运行时访问对象属性以进行序列化和反序列化。 作为替代方法,System.Text.Json
可以使用 C# 源生成功能来提高性能、降低专用内存使用量以及推动程序集修整,从而缩小应用大小。
有关详细信息,请参阅反射与源生成。
安全信息
有关在设计 JsonSerializer 时考虑的安全威胁以及如何缓解这些威胁的信息,请参阅 System.Text.Json
威胁模型。
线程安全
System.Text.Json
序列化程序在设计时考虑到了线程安全性。 实际上,这意味着锁定后,JsonSerializerOptions 实例就可以在多个线程之间安全地进行共享。 JsonDocument 为 JSON 值提供不可变且在 .NET 8 及更高版本中为线程安全的 DOM 表示形式。