当前位置: 首页 > news >正文

C#中System.Text.Json:从入门到精通的实用指南

一、引言

在当今数字化时代,数据的高效交换与处理成为软件开发的核心环节。JSON(JavaScript Object Notation)凭借其简洁、轻量且易于读写的特性,已然成为数据交换领域的中流砥柱。无论是前后端数据交互,还是配置文件的编写,亦或是分布式系统间的数据传输,JSON 都无处不在。

在 C# 的开发世界里,.NET Core 3.0 及更高版本引入的 System.Text.Json 库,为开发者提供了一套强大且高效的 JSON 序列化和反序列化解决方案。相较于旧有的库,它不仅性能卓越,还与.NET 平台深度集成,更契合现代化开发的需求。

本文将全方位、深入地探讨 System.Text.Json 库的使用方法,从基础的序列化与反序列化操作,到进阶的自定义转换器、属性控制等高级特性,通过丰富详实的代码示例,助力开发者熟练掌握这一强大工具,在项目开发中灵活运用,提升数据处理的效率与质量。

二、System.Text.Json 简介

2.1 是什么

System.Text.Json 是内置于.NET Core 3.0 及后续版本的高性能 JSON 序列化器 ,专为高效处理 JSON 数据而设计。其与.NET 平台深度融合,在性能、安全性及与现代开发模式的契合度上表现卓越。

在性能优化方面,System.Text.Json 采用了先进的算法与数据结构,在序列化和反序列化过程中,极大地减少了内存分配与对象创建次数。在处理大型 JSON 文档时,相较于部分传统 JSON 库,其速度优势显著。例如,在将复杂的业务对象转换为 JSON 字符串,或从庞大的 JSON 数据中还原对象时,能够快速完成操作,为应用程序节省宝贵的时间开销。

在安全性上,它默认采取了一系列安全措施,有效防范常见的安全风险。如在反序列化时,严格限制数据深度,避免因恶意构造的 JSON 数据导致的栈溢出攻击;对输入数据进行严格验证,防止非法数据注入,为应用程序筑牢安全防线。

此外,System.Text.Json 全面支持.NET 中的各种数据类型,无论是基本数据类型(如整数、字符串、布尔值等),还是复杂的自定义对象、泛型集合,抑或是日期时间类型等,都能精准地进行序列化和反序列化操作,确保数据在不同形式间的无损转换。

2.2 与其他 JSON 库对比

在.NET 开发领域,提及 JSON 处理,Newtonsoft.Json(即Json.NET)曾是广泛使用的库。然而,System.Text.Json 与之相比,具有独特优势。

从性能维度剖析,在处理大规模数据或高并发的序列化、反序列化场景时,System.Text.Json 的表现更为出色。在一个电商系统中,需频繁对大量商品信息(包含复杂的嵌套结构与海量数据)进行 JSON 序列化以传输给前端展示。经测试,使用 System.Text.Json 的处理速度比 Newtonsoft.Json 快了近 30%,内存占用也降低了约 25%。这得益于其底层针对 JSON 处理的优化设计,如更高效的编码方式、更合理的内存管理策略等。

在集成度方面,System.Text.Json 作为.NET Core 的内置库,与.NET 平台无缝集成。在创建ASP.NET Core Web API 项目时,默认的 JSON 序列化和反序列化功能就由 System.Text.Json 提供。开发者无需额外安装或配置,即可直接使用,大大简化了开发流程。而使用 Newtonsoft.Json 时,需通过 NuGet 包管理器进行安装,并进行相应的配置才能在项目中正常使用。

尽管 Newtonsoft.Json 功能丰富,在处理复杂 JSON 结构与某些特殊场景时具有较高灵活性,但 System.Text.Json 凭借其性能优势与深度集成特性,在现代化的.NET 开发中,尤其是注重性能与开发效率的项目里,正逐渐成为开发者的首选 。

三、使用前准备

3.1 环境要求

若想在项目中畅享 System.Text.Json 库带来的便利,项目的运行环境需满足一定条件。它最低要求项目基于.NET Core 3.0 版本及以上构建 。这意味着,若你的项目版本低于此标准,需将项目升级至.NET Core 3.0 或后续版本。

在 Visual Studio 中,右键点击项目名称,选择 “属性”。在弹出的属性窗口中,切换至 “目标框架” 下拉菜单,查看当前项目的目标框架版本。若版本低于.NET Core 3.0,可从下拉菜单中选择合适的更高版本进行升级。需注意,升级过程可能会因项目依赖、代码兼容性等问题,需要对部分代码进行调整与测试,以确保项目正常运行。

若因特殊原因无法升级项目框架,可考虑选用其他 JSON 处理库,如 Newtonsoft.Json 等,以满足项目对 JSON 数据处理的需求 。

3.2 安装与导入

当项目环境满足要求后,使用 System.Text.Json 库极为便捷。由于它是.NET Core 3.0 及更高版本的内置库,无需通过 NuGet 等包管理器进行额外安装。

在代码文件中,仅需在文件开头添加如下语句,即可导入 System.Text.Json 命名空间,开启对该库的使用之旅:

using System.Text.Json;

若在序列化或反序列化过程中,涉及对属性的自定义设置、处理复杂类型等操作,还需导入 System.Text.Json.Serialization 命名空间:

using System.Text.Json.Serialization;

如此一来,在当前代码文件中,便能自由调用 System.Text.Json 库中的各类方法与类型,如 JsonSerializer 类的 Serialize 和 Deserialize 方法,用于实现对象与 JSON 字符串之间的相互转换 。

四、基本使用方法

4.1 序列化基础

4.1.1 简单对象序列化

在实际开发中,将对象转换为 JSON 字符串是常见操作。以一个简单的Person类为例,展示如何利用 System.Text.Json 库实现对象的序列化。代码如下:

using System;
using System.Text.Json;public class Person
{public string Name { get; set; }public int Age { get; set; }
}class Program
{static void Main(){var person = new Person{Name = "张三",Age = 30};string jsonString = JsonSerializer.Serialize(person);Console.WriteLine(jsonString);}
}

上述代码中,首先定义了Person类,包含Name和Age两个属性。在Main方法中,创建了Person类的实例person,并为其属性赋值。接着,使用JsonSerializer.Serialize方法将person对象转换为 JSON 格式的字符串。执行该代码,控制台将输出如下结果:

{"Name":"张三","Age":30}

这便是Person对象序列化后的 JSON 字符串表示。通过这种方式,可方便地将对象数据在网络中传输,或存储到文件、数据库等介质中 。

4.1.2 复杂对象序列化

实际应用场景中,数据结构往往更为复杂,包含嵌套对象、集合等。假设有一个表示订单的Order类,其中包含客户信息、订单明细列表等。代码实现如下:

using System;
using System.Collections.Generic;
using System.Text.Json;public class Customer
{public string Name { get; set; }public string Email { get; set; }
}public class OrderItem
{public string ProductName { get; set; }public int Quantity { get; set; }public decimal Price { get; set; }
}public class Order
{public int OrderId { get; set; }public Customer Customer { get; set; }public List<OrderItem> OrderItems { get; set; }
}class Program
{static void Main(){var customer = new Customer{Name = "李四",Email = "lisi@example.com"};var orderItem1 = new OrderItem{ProductName = "笔记本电脑",Quantity = 1,Price = 5999.99m};var orderItem2 = new OrderItem{ProductName = "无线鼠标",Quantity = 2,Price = 99.99m};var order = new Order{OrderId = 1001,Customer = customer,OrderItems = new List<OrderItem> { orderItem1, orderItem2 }};string jsonString = JsonSerializer.Serialize(order);Console.WriteLine(jsonString);}
}

上述代码定义了Customer类、OrderItem类和Order类,其中Order类包含Customer类型的属性和OrderItem类型的集合属性。在Main方法中,创建了相应的对象实例,并将其组装成一个完整的订单信息。最后,通过JsonSerializer.Serialize方法对Order对象进行序列化。执行代码,输出的 JSON 字符串如下:

{"OrderId":1001,"Customer":{"Name":"李四","Email":"lisi@example.com"},"OrderItems":[{"ProductName":"笔记本电脑","Quantity":1,"Price":5999.99},{"ProductName":"无线鼠标","Quantity":2,"Price":99.99}]}

可以看到,System.Text.Json 库能够准确地将复杂对象结构序列化为对应的 JSON 格式,确保数据的完整性与准确性 。

4.2 反序列化基础

4.2.1 简单 JSON 字符串反序列化

将 JSON 字符串还原为对象,是与序列化相反的过程。对于简单的 JSON 字符串,使用 System.Text.Json 库进行反序列化同样便捷。以之前的Person类为例,假设从外部获取到一个 JSON 字符串,需要将其转换为Person对象。代码如下:

using System;
using System.Text.Json;public class Person
{public string Name { get; set; }public int Age { get; set; }
}class Program
{static void Main(){string jsonString = "{\"Name\":\"王五\",\"Age\":25}";Person person = JsonSerializer.Deserialize<Person>(jsonString);Console.WriteLine($"姓名: {person.Name}, 年龄: {person.Age}");}
}

在这段代码中,通过JsonSerializer.Deserialize方法,将包含Person对象信息的 JSON 字符串转换回Person类型的对象。Deserialize方法的泛型参数指定了要转换的目标类型。执行该代码,控制台将输出:

姓名: 王五, 年龄: 25

如此,便实现了简单 JSON 字符串到对象的反序列化操作,为后续对对象数据的处理提供了基础 。

4.2.2 处理复杂 JSON 结构反序列化

面对多层嵌套、数组等复杂结构的 JSON 数据,反序列化时需确保定义的类结构与 JSON 结构相匹配。例如,有如下复杂的 JSON 数据:

{"OrderId": 1002,"Customer": {"Name": "赵六","Email": "zhaoliu@example.com"},"OrderItems": [{"ProductName": "平板电脑","Quantity": 1,"Price": 2999.99},{"ProductName": "蓝牙键盘","Quantity": 1,"Price": 199.99}]
}

针对该 JSON 数据,反序列化的代码实现如下:

using System;
using System.Collections.Generic;
using System.Text.Json;public class Customer
{public string Name { get; set; }public string Email { get; set; }
}public class OrderItem
{public string ProductName { get; set; }public int Quantity { get; set; }public decimal Price { get; set; }
}public class Order
{public int OrderId { get; set; }public Customer Customer { get; set; }public List<OrderItem> OrderItems { get; set; }
}class Program
{static void Main(){string jsonString = @"{""OrderId"": 1002,""Customer"": {""Name"": ""赵六"",""Email"": ""zhaoliu@example.com""},""OrderItems"": [{""ProductName"": ""平板电脑"",""Quantity"": 1,""Price"": 2999.99},{""ProductName"": ""蓝牙键盘"",""Quantity"": 1,""Price"": 199.99}]}";Order order = JsonSerializer.Deserialize<Order>(jsonString);Console.WriteLine($"订单ID: {order.OrderId}");Console.WriteLine($"客户姓名: {order.Customer.Name}, 客户邮箱: {order.Customer.Email}");Console.WriteLine("订单明细:");foreach (var item in order.OrderItems){Console.WriteLine($"商品名称: {item.ProductName}, 数量: {item.Quantity}, 价格: {item.Price}");}}
}

在上述代码中,定义的Order类、Customer类和OrderItem类的结构与 JSON 数据结构一一对应。通过JsonSerializer.Deserialize方法,将复杂的 JSON 字符串成功转换为Order对象。随后,通过遍历Order对象的属性,输出订单的详细信息。执行代码,控制台将输出完整的订单信息,包括订单 ID、客户信息以及订单明细 。在处理复杂 JSON 结构反序列化时,准确匹配类结构至关重要,确保每个属性的名称、类型和层级关系与 JSON 数据一致,才能实现正确的反序列化。

五、进阶技巧

5.1 自定义序列化行为

5.1.1 自定义转换器

在实际开发中,默认的序列化和反序列化行为可能无法满足所有需求。例如,在处理日期类型时,若期望使用特定的日期格式进行序列化和反序列化,可通过自定义转换器实现。

以将日期格式化为 “yyyy-MM-dd” 为例,代码如下:

using System;
using System.Text.Json;
using System.Text.Json.Serialization;public class Person
{public string Name { get; set; }public DateTime BirthDate { get; set; }
}public class CustomDateTimeConverter : JsonConverter<DateTime>
{public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){return DateTime.ParseExact(reader.GetString(), "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);}public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options){writer.WriteStringValue(value.ToString("yyyy-MM-dd"));}
}class Program
{static void Main(){var options = new JsonSerializerOptions{Converters = { new CustomDateTimeConverter() }};var person = new Person{Name = "张三",BirthDate = new DateTime(1990, 1, 1)};string jsonString = JsonSerializer.Serialize(person, options);Console.WriteLine(jsonString);Person deserializedPerson = JsonSerializer.Deserialize<Person>(jsonString, options);Console.WriteLine($"姓名: {deserializedPerson.Name}, 出生日期: {deserializedPerson.BirthDate}");}
}

在上述代码中,首先定义了CustomDateTimeConverter类,它继承自JsonConverter,并重写了Read和Write方法。在Read方法中,将读取到的 JSON 字符串按照指定格式转换为DateTime类型;在Write方法中,将DateTime类型的值格式化为指定的字符串后写入 JSON。

接着,在JsonSerializerOptions中注册该自定义转换器。在进行序列化和反序列化操作时,使用包含自定义转换器的JsonSerializerOptions实例,从而实现对日期类型的自定义序列化和反序列化逻辑 。

5.1.2 使用特性控制序列化

System.Text.Json 提供了丰富的特性,用于精细控制属性在 JSON 中的序列化和反序列化行为。其中,JsonPropertyName特性尤为常用,可指定属性在 JSON 中的名称。

假设有如下Product类,希望在 JSON 中,ProductName属性显示为 “商品名称”,Price属性显示为 “价格”,代码实现如下:

using System.Text.Json.Serialization;public class Product
{[JsonPropertyName("商品名称")]public string ProductName { get; set; }[JsonPropertyName("价格")]public decimal Price { get; set; }
}

在进行序列化时,Product类的实例将按照特性指定的名称生成 JSON。例如:

using System.Text.Json;class Program
{static void Main(){var product = new Product{ProductName = "笔记本电脑",Price = 5999.99m};string jsonString = JsonSerializer.Serialize(product);Console.WriteLine(jsonString);}
}

执行上述代码,输出的 JSON 字符串为:

{"商品名称":"笔记本电脑","价格":5999.99}

通过这种方式,可灵活调整属性在 JSON 中的表示,使其更符合业务需求或外部接口的要求。此外,还有JsonIgnore特性,用于在序列化和反序列化时忽略某个属性;JsonRequired特性,用于指定某个属性在 JSON 中必须存在等,开发者可根据实际情况合理运用这些特性,优化 JSON 序列化和反序列化的效果 。

5.2 优化序列化与反序列化

5.2.1 性能优化策略

在处理大规模数据或对性能要求极高的场景下,优化 System.Text.Json 的序列化和反序列化性能至关重要。

从减少内存占用角度出发,可避免在序列化和反序列化过程中创建过多不必要的临时对象。在处理大型集合时,尽量使用Span和Memory等类型,这些类型提供了对内存的高效访问方式,减少了内存复制和垃圾回收的压力。在反序列化一个包含大量数据的 JSON 数组时,使用Utf8JsonReader直接读取 JSON 数据,并利用Span来处理数据,可有效降低内存占用。

为提高序列化和反序列化速度,可对常用的类型进行缓存。由于每次序列化和反序列化操作时,System.Text.Json 都需对类型信息进行解析和处理,通过缓存类型信息,可避免重复的解析工作,显著提升性能。可创建一个静态字典,用于存储已解析的类型信息,在进行序列化和反序列化操作前,先检查字典中是否存在对应的类型信息,若存在则直接使用,从而减少类型解析的时间开销。

此外,合理配置JsonSerializerOptions也能提升性能。在序列化时,可根据数据特点设置合适的Encoder,以减少字符编码转换的时间;在反序列化时,通过设置PropertyNameCaseInsensitive为true,可避免在属性名称匹配时进行大小写转换,提高匹配速度 。

5.2.2 处理特殊情况

在实际应用中,常遇到一些特殊情况,如处理空值、循环引用等,需进行特殊配置和处理。

当遇到空值时,可通过配置JsonSerializerOptions,设置DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,使序列化过程中忽略值为null的属性。例如:

using System.Text.Json;
using System.Text.Json.Serialization;public class Product
{public string Name { get; set; }public string Description { get; set; }
}class Program
{static void Main(){var product = new Product{Name = "鼠标",Description = null};var options = new JsonSerializerOptions{DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull};string jsonString = JsonSerializer.Serialize(product, options);Console.WriteLine(jsonString);}
}

上述代码中,由于Description属性值为null,且设置了忽略空值属性,输出的 JSON 字符串将不包含Description属性:

{"Name":"鼠标"}

若处理对象间的循环引用,可在JsonSerializerOptions中设置ReferenceHandler = ReferenceHandler.Preserve。假设存在两个相互引用的类ClassA和ClassB:

using System.Text.Json.Serialization;public class ClassB;public class ClassA
{public string Name { get; set; }public ClassB RelatedB { get; set; }
}public class ClassB
{public string Name { get; set; }public ClassA RelatedA { get; set; }
}

在进行序列化时,可通过如下方式处理循环引用:

using System.Text.Json;class Program
{static void Main(){var a = new ClassA{Name = "A实例",};var b = new ClassB{Name = "B实例",RelatedA = a};a.RelatedB = b;var options = new JsonSerializerOptions{ReferenceHandler = ReferenceHandler.Preserve};string jsonString = JsonSerializer.Serialize(a, options);Console.WriteLine(jsonString);}
}

通过上述配置,在序列化包含循环引用的对象时,System.Text.Json 会使用引用标识符来处理循环,避免无限递归,确保序列化和反序列化的正常进行 。

六、实际应用案例

6.1 Web API 数据交互

在ASP.NET Core Web API 开发中,System.Text.Json 扮演着关键角色,负责处理请求和响应数据的序列化与反序列化。

假设创建一个管理图书信息的 Web API。首先,定义Book类,用于表示图书信息:

public class Book
{public int Id { get; set; }public string Title { get; set; }public string Author { get; set; }public decimal Price { get; set; }
}

接着,在控制器中创建一个获取所有图书的方法。在这个方法中,从数据库或其他数据源获取图书列表,并将其作为响应返回给客户端。由于ASP.NET Core 默认使用 System.Text.Json 进行 JSON 序列化,返回的图书列表会自动序列化为 JSON 格式。代码如下:

[ApiController]
[Route("[controller]")]
public class BookController : ControllerBase
{private readonly List<Book> _books = new List<Book>{new Book { Id = 1, Title = "C#编程指南", Author = "张三", Price = 59.99m },new Book { Id = 2, Title = "ASP.NET Core实战", Author = "李四", Price = 79.99m }};[HttpGet]public IEnumerable<Book> GetBooks(){return _books;}
}

当客户端发送 GET 请求到/Book端点时,Web API 会将_books列表序列化为如下 JSON 格式的响应:

[{"Id": 1,"Title": "C#编程指南","Author": "张三","Price": 59.99},{"Id": 2,"Title": "ASP.NET Core实战","Author": "李四","Price": 79.99}
]

在接收客户端请求时,System.Text.Json 同样发挥作用。比如,创建一个添加图书的方法,客户端通过 POST 请求将图书信息以 JSON 格式发送到服务器,Web API 会自动将请求中的 JSON 数据反序列化为Book对象。代码如下:

[HttpPost]
public IActionResult AddBook([FromBody] Book book)
{_books.Add(book);return CreatedAtAction(nameof(GetBooks), new { id = book.Id }, book);
}

客户端发送的 POST 请求体可能如下:

{"Title": "新的图书","Author": "王五","Price": 49.99
}

Web API 接收到请求后,利用 System.Text.Json 将其反序列化为Book对象,进而完成图书添加操作 。通过这种方式,System.Text.Json 在 Web API 的数据交互中,实现了数据的高效、准确传输与处理,为前后端的顺畅通信提供了有力支持。

6.2 数据存储与读取

在实际项目中,常需将数据以 JSON 格式存储到文件或数据库中,以便后续读取和使用。借助 System.Text.Json 库,这一过程变得简单高效。

以将用户配置信息存储到文件为例,首先定义表示用户配置的类:

public class UserConfig
{public string Username { get; set; }public string Email { get; set; }public int Theme { get; set; }
}

在需要存储配置信息时,创建UserConfig对象实例,并将其序列化为 JSON 字符串后写入文件。代码如下:

var config = new UserConfig
{Username = "admin",Email = "admin@example.com",Theme = 1
};string jsonString = JsonSerializer.Serialize(config);
File.WriteAllText("config.json", jsonString);

上述代码将config对象序列化为 JSON 字符串,并使用File.WriteAllText方法将其写入名为config.json的文件中。

当需要读取配置信息时,从文件中读取 JSON 字符串,并将其反序列化为UserConfig对象。代码如下:

string json = File.ReadAllText("config.json");
UserConfig loadedConfig = JsonSerializer.Deserialize<UserConfig>(json);
Console.WriteLine($"用户名: {loadedConfig.Username}, 邮箱: {loadedConfig.Email}, 主题: {loadedConfig.Theme}");

在数据库存储方面,假设使用 SQLite 数据库,可将 JSON 数据存储在文本类型的字段中。在插入数据时,先将对象序列化为 JSON 字符串,再执行 SQL 插入语句。例如,使用Dapper库进行数据操作:

using Dapper;
using System.Data.SQLite;var person = new Person
{Name = "赵七",Age = 35
};string jsonPerson = JsonSerializer.Serialize(person);using (var connection = new SQLiteConnection("Data Source=test.db"))
{string insertQuery = "INSERT INTO People (JsonData) VALUES (@JsonData)";connection.Execute(insertQuery, new { JsonData = jsonPerson });
}

在读取数据时,从数据库中获取 JSON 字符串,再进行反序列化。代码如下:

using (var connection = new SQLiteConnection("Data Source=test.db"))
{string selectQuery = "SELECT JsonData FROM People WHERE Id = 1";string jsonResult = connection.QuerySingle<string>(selectQuery);Person retrievedPerson = JsonSerializer.Deserialize<Person>(jsonResult);Console.WriteLine($"姓名: {retrievedPerson.Name}, 年龄: {retrievedPerson.Age}");
}

通过这些示例可以看出,无论是文件存储还是数据库存储,System.Text.Json 库都能很好地实现数据的序列化存储与反序列化读取,确保数据的持久化与恢复 。

七、常见问题与解决方案

7.1 序列化和反序列化错误排查

在使用 System.Text.Json 进行序列化和反序列化操作时,难免会遭遇各种错误。其中,类型不匹配和属性丢失是较为常见的问题。

当出现类型不匹配的情况时,如在反序列化时,JSON 数据中的某个属性值的类型与目标类中对应属性的类型不一致,便会抛出异常。假设目标类中有一个int类型的属性,而 JSON 数据中该属性的值却是一个字符串,就会引发此类错误。此时,需仔细检查 JSON 数据与目标类的属性类型,确保二者完全匹配。在反序列化前,可对 JSON 数据进行预处理,将不匹配的类型转换为目标类型,或者调整目标类的属性类型以适应 JSON 数据。

属性丢失也是常见错误之一。若 JSON 数据中缺少目标类中某个必需的属性,在反序列化时,可能会导致属性值为默认值,或者抛出异常(取决于具体配置)。为解决该问题,可在目标类的属性上使用JsonPropertyName特性,明确指定 JSON 数据中对应的属性名称,防止因名称不一致导致的属性丢失。同时,在反序列化时,仔细检查 JSON 数据的结构,确保包含目标类所需的所有属性 。

7.2 性能瓶颈解决

尽管 System.Text.Json 在性能方面表现出色,但在特定场景下,仍可能出现性能瓶颈。

在处理超大规模数据时,序列化和反序列化的速度可能无法满足需求。此时,可通过优化数据结构来提升性能。减少不必要的嵌套层次,简化对象结构,能降低处理的复杂度。在序列化一个包含多层嵌套的复杂对象时,若某些嵌套层级并非必需,可将其扁平化处理,从而加快序列化和反序列化的速度。

若在高并发环境下,频繁的序列化和反序列化操作可能导致资源竞争和性能下降。针对这种情况,可采用缓存策略,将常用的序列化和反序列化结果进行缓存。在下次需要相同数据的转换时,先从缓存中获取,避免重复的转换操作,有效减轻系统负担,提升整体性能 。

八、总结与展望

System.Text.Json 库作为.NET 开发中处理 JSON 数据的核心工具,具备强大的功能与卓越的性能 。通过本文的深入探索,我们系统掌握了其基础与进阶用法。从简单对象到复杂结构的序列化与反序列化,再到自定义序列化行为、优化性能等操作,开发者能够依据不同的业务需求,灵活运用该库实现高效的数据处理。

展望未来,随着.NET 技术的持续演进,System.Text.Json 库有望在性能、功能及易用性方面实现更大突破。在面对日益复杂的应用场景与海量数据时,相信它将提供更强大的解决方案,助力开发者轻松应对各种挑战。

衷心希望本文能成为你在使用 System.Text.Json 库道路上的得力指南,为你的开发工作注入新的活力与效率。期待你在实际项目中充分发挥其优势,创造出更优秀的应用程序 。

相关文章:

C#中System.Text.Json:从入门到精通的实用指南

一、引言 在当今数字化时代&#xff0c;数据的高效交换与处理成为软件开发的核心环节。JSON&#xff08;JavaScript Object Notation&#xff09;凭借其简洁、轻量且易于读写的特性&#xff0c;已然成为数据交换领域的中流砥柱。无论是前后端数据交互&#xff0c;还是配置文件…...

【深度学习】Huber Loss详解

文章目录 1. Huber Loss 原理详解2. Pytorch 代码详解3.与 MSELoss、MAELoss 区别及各自优缺点3.1 MSELoss 均方误差损失3.2 MAELoss 平均绝对误差损失3.3 Huber Loss 4. 总结4.1 优化平滑4.2 梯度较好4.3 为什么说 MSE 是平滑的 1. Huber Loss 原理详解 Huber Loss 是一种结合…...

Maven下载配置

目录 Win下载配置maven的环境变量 Mac下载安装配置环境变量 MavenSetting.xml文件配置 Win 下载 https://maven.apache.org/ 在主页面点击Download 点击archives 最好不要下载使用新版本&#xff0c;我使用的是maven-3.6.3&#xff0c;我们点击页面下方的archives&#xff0…...

JS基础(5):运算符和语句

一.运算符 1.赋值运算符 加减乘除都是一样的&#xff0c;&#xff0c;-&#xff0c;*&#xff0c;/ 2.一元运算符&#xff1a;经常用来计数 自增&#xff1a; 每次只能加一 自减&#xff1a;-- 前置自增 后置自增 结…...

游戏引擎学习第81天

仓库:https://gitee.com/mrxiao_com/2d_game_2 或许我们应该尝试在地面上添加一些绘图 在这段时间的工作中&#xff0c;讨论了如何改进地面渲染的问题。虽然之前并没有专注于渲染部分&#xff0c;因为当时主要的工作重心不在这里&#xff0c;但在实现过程中&#xff0c;发现地…...

网络安全 | 什么是正向代理和反向代理?

关注&#xff1a;CodingTechWork 引言 在现代网络架构中&#xff0c;代理服务器扮演着重要的角色。它们在客户端和服务器之间充当中介&#xff0c;帮助管理、保护和优化数据流。根据代理的工作方向和用途&#xff0c;代理服务器可分为正向代理和反向代理。本文将深入探讨这两种…...

前缀和——模板 二维前缀和

一.题目描述 【模板】二维前缀和_牛客题霸_牛客网 二.题目解析 这道题和上一道题有点异曲同工之妙。输入一个m行n列的矩阵&#xff0c;然后进行q次操作&#xff0c;每次操作输入4个数&#xff0c;作为两个点的坐标&#xff0c;计算这两个点为对角线的矩阵的和。 三.算法原理 …...

oracle使用case when报错ORA-12704字符集不匹配原因分析及解决方法

问题概述 使用oracle的case when函数时&#xff0c;报错提示ORA-12704字符集不匹配&#xff0c;如下图&#xff0c;接下来分析报错原因并提出解决方法。 样例演示 现在有一个TESTTABLE表&#xff0c;本表包含的字段如下图所示&#xff0c;COL01字段是NVARCHAR2类型&#xff0…...

高等数学学习笔记 ☞ 定积分与积分公式

1. 定积分的基本概念 1.1 定积分的定义 1. 定义&#xff1a;设函数在闭区间上有界。在闭区间上任意插入若干个分点&#xff0c;即&#xff0c; 此时每个小区间的长度记作(不一定是等分的)。然后在每个小区间上任意取&#xff0c;对应的函数值为。 为保证每段的值(即矩形面积)无…...

MLMs之Agent:Phidata的简介、安装和使用方法、案例应用之详细攻略

MLMs之Agent&#xff1a;Phidata的简介、安装和使用方法、案例应用之详细攻略 目录 Phidata简介 Phidata安装和使用方法 1、安装 2、使用方法 (1)、认证 (2)、创建 Agent (3)、运行 Agent (4)、Agent Playground Phidata 案例应用 1、多工具 Agent 2、多模态 Agent …...

如何在不暴露MinIO地址的情况下,用Spring Boot与KKFileView实现文件预览

在现代Web应用中&#xff0c;文件预览是一项常见且重要的功能。它允许用户在不上传或下载文件的情况下&#xff0c;直接在浏览器中查看文件内容。然而&#xff0c;直接将文件存储服务&#xff08;如MinIO&#xff09;暴露给前端可能会带来安全风险。本文将介绍如何在不暴露MinI…...

ESP8266固件烧录

一、烧录原理 1、引脚布局 2、引脚定义 3、尺寸封装 4、环境要求 5、接线方式 ESP8266系列模块集成了高速GPI0和外围接口&#xff0c;这可能会导致严重的开关噪声。如果某些应用需要高功率和EMI特性&#xff0c;建议在数字I/0线上串联10到100欧姆。这可以在切换电源时抑制过冲…...

Python 模拟真人鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…...

三天急速通关Java基础知识:Day1 基本语法

三天急速通关JAVA基础知识&#xff1a;Day1 基本语法 0 文章说明1 关键字 Keywords2 注释 Comments2.1 单行注释2.2 多行注释2.3 文档注释 3 数据类型 Data Types3.1 基本数据类型3.2 引用数据类型 4 变量与常量 Variables and Constant5 运算符 Operators6 字符串 String7 输入…...

免费使用 Adobe 和 JetBrains 软件的秘密

今天想和大家聊聊如何利用 Edu 教育邮箱免费使用 Photoshop、Illustrator 等 Adobe 系列软件&#xff0c;以及 JetBrains 开发工具。 首先&#xff0c;Adobe 的软件是设计师的必备工具。无论是处理图像的 Photoshop&#xff0c;还是进行矢量设计的 Illustrator&#xff0c;它们…...

Pytorch 自学笔记(三):利用自定义文本数据集构建Dataset和DataLoader

Pytorch 自学笔记&#xff08;三&#xff09; 1. Dataset与DataLoader1.1 torch.utils.data.Dataset1.2 torch.utils.data.DataLoader Pytorch 自学笔记系列的第三篇。针对Pytorch的Dataset和DataLoader进行简单的介绍&#xff0c;同时&#xff0c;介绍如何使用自定义文本数据集…...

gradle项目的创建和基本结构简介

文章目录 创建gradle项目&#xff08;命令行&#xff09;创建gradle项目&#xff08;IDEA&#xff09;项目基本结构和功能Gradle 构建流程测试类体验 创建gradle项目&#xff08;命令行&#xff09; yangMacdeMac-mini gradleStudy % gradle init Starting a Gradle Daemon (s…...

wow-agent---Day3 Zigent 智能代理开发框架

这个框架是课程讲解的&#xff0c;但资料比较少&#xff0c;觉得框架比较小众&#xff0c;所以这里只分析代码&#xff0c;打算把更多的精力放在metagpt的学习上&#xff0c;毕竟还是要学教为主流的框架&#xff0c;这对后续维护升级都有帮助&#xff0c;当然感兴趣作为研究&am…...

python 入门

1. Python 概述 1.1 简介 python 是一种面向对象的解释型编程语言&#xff0c;由吉多范罗苏姆开发&#xff1b; 1991 年&#xff0c;公开发行版发布&#xff1b; 因其可以将其他语言制作的模块轻松联接在一起&#xff0c;又被称作胶水语言&#xff1b; 1.2 优点 简单易学&…...

sentinel微服务保护

学习链接 SpringCloudRabbitMQDockerRedis搜索分布式 文章目录 学习链接1.初识Sentinel1.1.雪崩问题及解决方案1.1.1.雪崩问题1.1.2.超时处理1.1.3.仓壁模式1.1.4.断路器1.1.5.限流1.1.6.总结 1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel官网地址github地址…...

接口测试Day10-封装IHRM登录

-登录接口 普通方式实现 登录接口对象层 思路&#xff1a; 动态变化的&#xff0c;写入参数固定不变&#xff0c;直接写到方法实现内响应结果&#xff0c;通过返回值 return 分析&#xff1a; 封装实现&#xff1a; 登录接口测试用例层 封装断言方法 1、创建 文件 assert_uti…...

什么是IP地址、子网掩码、网关、DNS

简单解释 IP地址在网络中用于标识一个节点(或者网络设备的接口) IP地址用于IP报文在网络中的寻址 一个IPv4地址有32 bit。 IPv4地址通常采用“点分十进制”表示。 IPv4地址范围:0.0.0.0~255.255.255.255 网络部分:用来标识一个网络&#xff0c;代表IP地址所属网络。 主机部分:…...

python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)角点检测

角点检测&#xff08;Corner Detection&#xff09;是计算机视觉和图像处理中重要的步骤&#xff0c;主要用于提取图像中的关键特征&#xff0c;以便进行后续的任务&#xff0c;比如图像匹配、物体识别、运动跟踪等。下面介绍几种常用的角点检测方法及其应用。 1. Harris角点检…...

软路由系统iStoreOS 一键安装 docker compose

一键安装命令 大家好&#xff01;今天我来分享一个快速安装 docker-compose 的方法。以下是我常用的命令&#xff0c;当前版本是 V2.32.4。如果你需要最新版本&#xff0c;可以查看获取docker compose最新版本号 部分&#xff0c;获取最新版本号后替换命令中的版本号即可。 w…...

Invicti-Professional-V25.1

01 更新介绍 此更新包括对内部代理的更改。内部扫描代理的当前版本为 25.1.0。内部身份验证验证程序代理的当前版本为 25.1.0。#新功能现在&#xff0c;单击扫描摘要屏幕中的预设扫描图标会将您重定向到具有过滤视图的 “最近扫描” 页面&#xff0c;从而改进导航和对相关扫描…...

【QT】: 初识 QWidget 控件 | QWidget 核心属性(API) | qrc 文件

&#x1f525; 目录 1. 控件概述 控件体系的发展阶段 2. QWidget 核心属性 2.1 核心属性概览2.2 用件可用&#xff08;Enabled&#xff09; 2.3 坐标系&#xff08;Geometry&#xff09; **实例 1: 控制按钮的位置**实例 2: 表白 程序 2.4 窗口标题&#xff08;windowTiltle&a…...

Spring WebFlux

文章目录 一、概述1、Spring体系定位2、Spring MVC和WebFlux差异 二、入门1、依赖2、ReactorHttpHandlerAdapter&#xff08;main启动&#xff09;3、DispatcherHandler&#xff08;SpringWebFlux启动&#xff09;4、WebFilter 三、DispatcherHandler理解1、handle 前置知识&am…...

【AI | pytorch】torch.polar的使用

一、torch.polar的使用 torch.polar 是 PyTorch 中用来生成复数张量的一个函数&#xff0c;但它与数学中的复数表达式 ( z re^{i\theta} ) 是等价的。 具体来说&#xff0c;torch.polar(abs, angle) 接受两个实数张量参数&#xff1a; abs&#xff1a;表示复数的模长&#…...

AWTK fscript 中的 输入/出流 扩展函数

fscript 是 AWTK 内置的脚本引擎&#xff0c;开发者可以在 UI XML 文件中直接嵌入 fscript 脚本&#xff0c;提高开发效率。本文介绍一下 fscript 中的 iostream 扩展函数 1.iostream_get_istream 获取输入流对象。 原型 iostream_get_istream(iostream) > object示例 va…...

【多线程】线程池

一、什么是线程池 线程池&#xff08;Thread Pool&#xff09;是一种多线程并发执行的设计模式&#xff0c;它通过维护一个线程集合来执行多个任务&#xff0c;避免频繁地创建和销毁线程&#xff0c;提高系统性能和响应速度。 就好比如你经营了一家餐饮店&#xff0c;你名下有…...

小结:路由器配置和管理 RIP协议

华为路由器中配置和管理 RIP&#xff08;Routing Information Protocol&#xff09;的相关指令主要分为以下几个部分&#xff1a;基础配置指令、接口配置指令、路由控制指令和调试指令。以下是总结&#xff1a; 1. 启用 RIP 协议 [Huawei] rip 1rip 1&#xff1a;表示创建并启…...

基于海思soc的智能产品开发(高、中、低soc、以及和fpga的搭配)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 市场上关于图像、音频的soc其实非常多&#xff0c;这里面有高、中、低档&#xff0c;开发方式也不相同。之所以会这样&#xff0c;有价格的因素&am…...

于灵动的变量变幻间:函数与计算逻辑的浪漫交织(下)

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。 这一节我们主要来学习单个函数的声明与定义&#xff0c;static和extern… 这里写目录标题 一、单个函数…...

偷偷的学Java

序章&#xff1a;为何要偷偷学Java&#xff1f; • Java&#xff0c;不仅仅是一种编程语言 • 偷偷学Java&#xff0c;快速提升你的竞争力 •Java学习秘籍 第一章&#xff1a;Java的神秘面纱 •Java的起源与发展历程 •Java的生态系统与应用场景 • Java与其他编程语言的…...

以单用户模式启动 Linux 的方法

注&#xff1a;本文为 “Linux 启动单用户模式” 相关文章合辑。 未整理去重。 以单用户模式启动 linux 的三种方法 作者&#xff1a; Magesh Maruthamuthu 译者&#xff1a; LCTT Xiaobin.Liu 2020-05-03 23:01 单用户模式&#xff0c;也被称为维护模式&#xff0c;超级用户…...

【AI论文】生成式视频模型是否通过观看视频学习物理原理?

摘要&#xff1a;AI视频生成领域正经历一场革命&#xff0c;其质量和真实感在迅速提升。这些进步引发了一场激烈的科学辩论&#xff1a;视频模型是否学习了能够发现物理定律的“世界模型”&#xff0c;或者&#xff0c;它们仅仅是复杂的像素预测器&#xff0c;能够在不理解现实…...

【有啥问啥】Contrastive Captioners(CoCa):对比式图像描述模型——图像-文本基础模型的新范式

Contrastive Captioners(CoCa)&#xff1a;对比式图像描述模型——图像-文本基础模型的新范式 引言 随着深度学习技术的发展&#xff0c;多模态模型在处理视觉和语言任务方面的能力逐渐增强。特别是大规模预训练模型的兴起&#xff0c;使得这些模型可以快速迁移到许多下游任务…...

Python(十七)excel指定列自动翻译成英文

前言 本章主要讲述在excel的指定列后面添加一列&#xff0c;并翻译成英文 一、效果图 二、代码 实际需求&#xff1a; # -*- codeing utf-8 -*- # time: 2025/1/16 16:32 # Author : Mikasa # # Aim&#xff1a;自动将客户发的货物清单里的商品名称&#xff0c;翻译成英文…...

【论文投稿】探秘计算机视觉算法:开启智能视觉新时代

目录 引言 一、计算机视觉算法基石&#xff1a;图像基础与预处理 二、特征提取&#xff1a;视觉信息的精华萃取 三、目标检测&#xff1a;从图像中精准定位目标 四、图像分类&#xff1a;识别图像所属类别 五、语义分割&#xff1a;理解图像的像素级语义 六、计算机视觉…...

【机器学习实战入门】使用LSTM机器学习预测股票价格

机器学习在股票价格预测中有重要的应用。在这个机器学习项目中&#xff0c;我们将讨论如何预测股票的收益。这是一个非常复杂的任务&#xff0c;充满了不确定性。我们将会把这个项目分成两部分进行开发&#xff1a; 首先&#xff0c;我们将学习如何使用 LSTM 神经网络预测股票…...

(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及OpenCV完整代码实战(C++版)

一、四大坐标系介绍 1&#xff0c;世界坐标系 从这个世界&#xff08;world&#xff09;的视角来看物体 世界坐标系是3D空间坐标&#xff0c;每个点的位置用 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw​,Yw​,Zw​)表示 2&#xff0c;相机坐标系 相机本身具有一个坐标系&…...

Bootstrap 下拉菜单

Bootstrap 下拉菜单 Bootstrap 是一个流行的前端框架&#xff0c;它提供了许多预构建的组件&#xff0c;其中之一就是下拉菜单。下拉菜单是一个交互式元素&#xff0c;允许用户从一系列选项中选择一个。在本篇文章中&#xff0c;我们将详细介绍如何在 Bootstrap 中创建和使用下…...

WinHttp API接口辅助类实现GET POST网络通讯

1、简述 近期需要在MFC基础上开发网络Http通讯,开始使用的WinINet进行通讯,后面发现WinINet对连接超时这块不支持设置,在网上搜索了几种方式效果都不太好,于是决定用WinHttp API接口进行通讯,分别对GET、POST进行了封装。 2、使用到接口 2.1、WinHttpOpen WinHttpOpen 是…...

Elasticsearch实战应用

嘿&#xff0c;小伙伴们&#xff0c;今天咱们来唠唠Elasticsearch&#xff0c;这可是个超厉害的搜索引擎&#xff0c;能帮你在海量数据里快速找到想要的东西&#xff0c;就像给你的数据装上了“放大镜”。 一、啥是Elasticsearch 简单来说&#xff0c;Elasticsearch就是一个基…...

MySQL存储过程

存储过程: 事先经过编译并存储在数据库中的一段sql语句的集合&#xff0c;调用存储过程可以简化应用开发人员的很多工作&#xff0c;减少数据在数据库和应用服务器之间的传输&#xff0c;对于提高数据处理的效率是有好处的&#xff0c;思想上就是sql语言层面的代码封装与重用 …...

安路FPGA开发工具TD:问题解决办法 及 Tips 总结

安路科技&#xff08;Anlogic&#xff09;是一家专注于高性能、低功耗可编程逻辑器件&#xff08;FPGA&#xff09;设计和生产的公司。其提供的开发工具TD&#xff08;TangDynasty&#xff09;是专门为安路FPGA系列产品设计的集成开发环境&#xff08;IDE&#xff09;。以下是对…...

高精度阶乘C++实现

高精度计算&#xff0c;实际上就是模拟竖式计算&#xff0c;代码如下&#xff0c;请慢慢消化&#xff0c;如有不足或建议&#xff0c;请在评论区留言 这个阶乘操作实际上就是高精度乘法的运用&#xff0c;可以非常容易的在考场上写出来 #include <bits/stdc.h> using na…...

PageHelper快速使用

依赖 <!--分页插件PageHelper--> <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.7</version> </dependency>示例 /** * 封装分页结果…...

“AI 辅助决策系统:决策路上的智慧领航员

在当今瞬息万变的时代&#xff0c;无论是企业的运营管理&#xff0c;还是个人在生活中的重大抉择&#xff0c;都需要精准、高效的决策。然而&#xff0c;信息的繁杂和未来的不确定性&#xff0c;常常让决策变得困难重重。这时&#xff0c;AI 辅助决策系统宛如一位智慧的领航员&…...

[Linux] linux 系统中如何添加自动启动程序

背景&#xff1a;在嵌入式系统中&#xff0c;需要开机自动启动所编写的程序【可执行文件】。 解决方法&#xff1a;原理就是Linux开机会自动执行一些文件。在/etc/profile中添加执行程序的脚本。/etc/profile 是一个系统级的配置文件&#xff0c;在用户登录Linux系统时自动执行…...