深入理解 .NET 6 的 JSON DOM API: 使用 System.Text.Json 操作 JSON
在现代应用开发中,JSON(JavaScript Object Notation)已成为数据交换的主流格式之一。无论是前后端通信,还是与第三方 API 的交互,JSON 格式的灵活性和可读性都使它在众多场景中大放异彩。在 .NET 生态中,System.Text.Json
是一个轻量级、高性能的库,用于序列化和反序列化 JSON 数据。在 .NET 6 中,该库进一步增强,特别是其 JSON DOM(文档对象模型)API,提供了更加灵活和高效的方式操作 JSON 数据。
本文将详细讲解如何利用 .NET 6 的 JSON DOM API 处理 JSON 数据,从基本的读写操作到高级的动态操作和性能优化。
什么是 JSON DOM API?
JSON DOM API 是 System.Text.Json
提供的一组类,用于将 JSON 文档解析为可操作的 DOM 树。这种方式使开发者可以动态地读取、修改和写回 JSON 数据,而不需要将其绑定到强类型对象。主要涉及以下核心类:
JsonDocument
:只读表示 JSON 文档,适合用于解析和读取 JSON 数据。JsonElement
:表示 JSON 数据的单个元素,可以是对象、数组、值等。JsonNode
:新增于 .NET 6,用于动态读写 JSON 数据。它是一个抽象类,有三个具体实现:JsonObject
:表示 JSON 对象。JsonArray
:表示 JSON 数组。JsonValue
:表示简单值类型(如字符串、数字、布尔值等)。
JSON DOM API 的设计目标是性能优先,同时提供动态操作的灵活性。
为什么选择 JSON DOM API?
使用 JSON DOM API 的场景主要包括:
- 动态 JSON 操作:当 JSON 结构在编译时未知,或部分未知时,JSON DOM API 提供了灵活的读写能力。
- 局部数据处理:无需将整个 JSON 文档序列化到对象中,而是直接操作其中的部分数据,减少开销。
- 高性能要求:与传统的 Newtonsoft.Json 比较,
System.Text.Json
的性能表现更优,占用更少的内存。
基础用法:解析和读取 JSON
以下是一个解析 JSON 数据并读取内容的示例:
using System;
using System.Text.Json;
class Program
{
static void Main()
{
string jsonString = @"
{
""name"": ""John Doe"",
""age"": 30,
""skills"": [""C#"", "".NET"", ""System.Text.Json""]
}";
using JsonDocument document = JsonDocument.Parse(jsonString);
JsonElement root = document.RootElement;
// 读取根元素的属性
string name = root.GetProperty("name").GetString();
int age = root.GetProperty("age").GetInt32();
// 遍历数组
JsonElement skills = root.GetProperty("skills");
foreach (JsonElement skill in skills.EnumerateArray())
{
Console.WriteLine(skill.GetString());
}
Console.WriteLine($"Name: {name}, Age: {age}");
}
}
输出结果:
C#
.NET
System.Text.Json
Name: John Doe, Age: 30
解析逻辑详解
JsonDocument.Parse
:将 JSON 字符串解析为JsonDocument
,这是一个只读表示,不支持修改。JsonElement
:RootElement
表示 JSON 的根对象,可通过GetProperty
方法访问属性。- 数组操作:使用
EnumerateArray
遍历数组元素。
使用 JsonNode 动态操作 JSON
如果需要修改 JSON 数据,可以使用 JsonNode
。它支持动态增删改查,并能轻松序列化回字符串。
示例:创建和修改 JSON
using System;
using System.Text.Json;
using System.Text.Json.Nodes;
class Program
{
static void Main()
{
// 动态创建 JSON
var jsonObject = new JsonObject
{
["name"] = "Jane Doe",
["age"] = 28,
["skills"] = new JsonArray("C#", "ASP.NET", "System.Text.Json")
};
// 修改 JSON 数据
jsonObject["age"] = 29; // 更新年龄
((JsonArray)jsonObject["skills"]).Add("Azure"); // 添加新技能
// 打印结果
string updatedJson = jsonObject.ToJsonString(new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(updatedJson);
}
}
输出结果:
{
"name": "Jane Doe",
"age": 29,
"skills": [
"C#",
"ASP.NET",
"System.Text.Json",
"Azure"
]
}
动态操作解析
- 动态创建 JSON:
JsonObject
和JsonArray
的构造函数非常直观,支持链式初始化。 - 修改数据:直接通过索引器修改或添加属性。
- 序列化:
ToJsonString
方法将节点重新序列化为 JSON 字符串。
高级用法:处理复杂 JSON
对于嵌套结构较深或需要动态处理的大型 JSON 文档,可以结合 JsonNode
和 LINQ。
示例:从复杂 JSON 提取特定数据
using System;
using System.Text.Json;
using System.Text.Json.Nodes;
class Program
{
static void Main()
{
string jsonString = @"
{
""employees"": [
{ ""id"": 1, ""name"": ""Alice"", ""department"": ""Engineering"" },
{ ""id"": 2, ""name"": ""Bob"", ""department"": ""HR"" },
{ ""id"": 3, ""name"": ""Charlie"", ""department"": ""Engineering"" }
]
}";
var root = JsonNode.Parse(jsonString);
var employees = root?["employees"]?.AsArray();
if (employees != null)
{
// 筛选出工程部员工
foreach (var employee in employees)
{
if (employee?["department"]?.GetValue<string>() == "Engineering")
{
Console.WriteLine(employee?["name"]?.GetValue<string>());
}
}
}
}
}
输出结果:
Alice
Charlie
性能优化技巧
- 避免重复解析:对于频繁使用的 JSON 数据,尽量将其解析为 DOM 或强类型对象,避免多次调用
Parse
。 - 使用池化选项:通过
JsonDocumentOptions
控制内存池分配。 - 合理选择 API:
JsonNode
动态操作方便,但JsonDocument
在只读场景中更高效。
与 Newtonsoft.Json 的比较
功能 |
System.Text.Json |
Newtonsoft.Json |
---|---|---|
性能 |
高 |
较低 |
动态操作 |
支持(JsonNode) |
支持(JObject/JArray) |
特性支持 |
支持部分(如 JsonIgnore) |
更全面 |
跨平台支持 |
优秀 |
优秀 |
System.Text.Json
是现代 .NET 应用的首选,特别是在性能敏感的场景中。
.NET 6 的 JSON DOM API 提供了一种灵活、高效的方式操作 JSON 数据。从基础的只读操作到动态的增删改,System.Text.Json
的功能覆盖了广泛的应用场景。通过合理选择和优化,可以充分发挥其性能优势,使你的应用在处理 JSON 数据时更加得心应手。
- 点赞
- 收藏
- 关注作者
评论(0)