深入理解 .NET 6 的 JSON DOM API: 使用 System.Text.Json 操作 JSON

举报
Rolle 发表于 2024/11/30 13:38:57 2024/11/30
【摘要】 在现代应用开发中,JSON(JavaScript Object Notation)已成为数据交换的主流格式之一。无论是前后端通信,还是与第三方 API 的交互,JSON 格式的灵活性和可读性都使它在众多场景中大放异彩。在 .NET 生态中,System.Text.Json 是一个轻量级、高性能的库,用于序列化和反序列化 JSON 数据。在 .NET 6 中,该库进一步增强,特别是其 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 数据,而不需要将其绑定到强类型对象。主要涉及以下核心类:

  1. JsonDocument:只读表示 JSON 文档,适合用于解析和读取 JSON 数据。
  2. JsonElement:表示 JSON 数据的单个元素,可以是对象、数组、值等。
  3. JsonNode:新增于 .NET 6,用于动态读写 JSON 数据。它是一个抽象类,有三个具体实现:
    • JsonObject:表示 JSON 对象。
    • JsonArray:表示 JSON 数组。
    • JsonValue:表示简单值类型(如字符串、数字、布尔值等)。

JSON DOM API 的设计目标是性能优先,同时提供动态操作的灵活性。


为什么选择 JSON DOM API?

使用 JSON DOM API 的场景主要包括:

  1. 动态 JSON 操作:当 JSON 结构在编译时未知,或部分未知时,JSON DOM API 提供了灵活的读写能力。
  2. 局部数据处理:无需将整个 JSON 文档序列化到对象中,而是直接操作其中的部分数据,减少开销。
  3. 高性能要求:与传统的 Newtonsoft.Json 比较,System.Text.Json 的性能表现更优,占用更少的内存。

基础用法:解析和读取 JSON

以下是一个解析 JSON 数据并读取内容的示例:

代码语言:javascript
复制
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}");
    }
}

输出结果

代码语言:javascript
复制
C#
.NET
System.Text.Json
Name: John Doe, Age: 30

解析逻辑详解

  1. JsonDocument.Parse:将 JSON 字符串解析为 JsonDocument,这是一个只读表示,不支持修改。
  2. JsonElementRootElement 表示 JSON 的根对象,可通过 GetProperty 方法访问属性。
  3. 数组操作:使用 EnumerateArray 遍历数组元素。

使用 JsonNode 动态操作 JSON

如果需要修改 JSON 数据,可以使用 JsonNode。它支持动态增删改查,并能轻松序列化回字符串。

示例:创建和修改 JSON

代码语言:javascript
复制
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);
    }
}

输出结果

代码语言:javascript
复制
{
  "name": "Jane Doe",
  "age": 29,
  "skills": [
    "C#",
    "ASP.NET",
    "System.Text.Json",
    "Azure"
  ]
}

动态操作解析

  1. 动态创建 JSONJsonObjectJsonArray 的构造函数非常直观,支持链式初始化。
  2. 修改数据:直接通过索引器修改或添加属性。
  3. 序列化ToJsonString 方法将节点重新序列化为 JSON 字符串。

高级用法:处理复杂 JSON

对于嵌套结构较深或需要动态处理的大型 JSON 文档,可以结合 JsonNode 和 LINQ。

示例:从复杂 JSON 提取特定数据

代码语言:javascript
复制
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>());
                }
            }
        }
    }
}

输出结果

代码语言:javascript
复制
Alice
Charlie

性能优化技巧

  1. 避免重复解析:对于频繁使用的 JSON 数据,尽量将其解析为 DOM 或强类型对象,避免多次调用 Parse
  2. 使用池化选项:通过 JsonDocumentOptions 控制内存池分配。
  3. 合理选择 APIJsonNode 动态操作方便,但 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 数据时更加得心应手。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。