在 C# 中System.Text.Json的使用

作者:微信公众号:【架构师老卢】
8-28 15:31
7

概述:如何使用命名空间在 C# 中序列化和反序列化 JSON。System.Text.Json注意:您可以使用您最喜欢的在线 C# 编译器(如 ShartLab.io)尝试本文中所示的示例。什么是 JSON?JSON 代表 JavaScript 对象表示法,它主要用于在两个可能位于同一平台上也可能不在同一平台上的系统之间建立通信。早期使用的是 XML,但是,XML 难以生成和解析,并且对人类不太友好。相比之下,JSON 易于理解、编写且重量轻。什么是 System.Text.JSON 以及为什么我们在 C# 中需要它?System.Text.JSON是一个命名空间,这意味着它包含类、帮助程序和扩展方

如何使用命名空间在 C# 中序列化和反序列化 JSON。System.Text.Json

注意:您可以使用您最喜欢的在线 C# 编译器(如 ShartLab.io)尝试本文中所示的示例。

什么是 JSON?

JSON 代表 JavaScript 对象表示法,它主要用于在两个可能位于同一平台上也可能不在同一平台上的系统之间建立通信。早期使用的是 XML,但是,XML 难以生成和解析,并且对人类不太友好。

相比之下,JSON 易于理解、编写且重量轻。

什么是 System.Text.JSON 以及为什么我们在 C# 中需要它?

System.Text.JSON是一个命名空间,这意味着它包含类、帮助程序和扩展方法,用于处理与 JSON 对象相关的各种操作。以下是我们需要它的主要原因:

  1. 序列化/反序列化: 它是指将 C# 对象转换为 JSON(序列化)字符串或从 JSON 字符串转换为 C# 对象(反序列化)。
  2. 自定义转换: 我们可以创建一个自定义转换器来处理转换时非常特定的场景。它可以包括、忽略某些属性、重命名某些属性等。
  3. 部分 JSON 读取: 假设我们有一个大型而复杂的 JSON 对象,我们只需要解析它的一部分。我们可以在不使用命名空间中可用的方法将整个 JSON 转换为 C# 对象的情况下做到这一点。
  4. 流支持: 我们可以增量生成 JSON 对象,就像动态流式传输数据一样。例如,我们正在读取一个很长的列表,并希望根据某些条件生成 JSON。
  5. 内存效率: 它使用 Span<T> 和 Memory<T> 来有效地使用内存。

让我们通过示例了解更多关于上述产品的信息。

序列化/反序列化

让我们看一个非常基本的 Serialization 示例:

using System;  
using System.Text.Json;  
  
public class Person    
{  
    public string Name { get; set; }  
    public int Age { get; set; }  
}  
  
public class Program    
{  
    public static void Main()  
    {  
        Person person = new() { Name = "John", Age = 30 };  
  
        // Serialize to JSON   
        string jsonString = JsonSerializer.Serialize(person);  
        Console.WriteLine(jsonString);  
  
        // Deserialize from JSON   
        Person deserializedPerson = JsonSerializer.Deserialize\<Person>(jsonString);  
        Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");  
    }  
}
Output  
  
{"Name":"John","Age":30}  
Name: John, Age: 30

这里我们声明了一个名为 .稍后使用 method,该方法将 C# 对象作为参数并返回 string,我们将对象转换为 JSON 字符串。接下来,我们使用相同的字符串将其转换回 C# 对象。PersonJsonSerializer.SerializePerson {"Name":"John", "Age": 30}JsonSerializer.Deserialize<Person>(jsonString)

很简单,对吧?

自定义转化

假设我们想在 Serializing 时忽略该属性。以下是我们如何做到这一点:Age

using System;  
using System.Text.Json;  
using System.Text.Json.Serialization;  
  
public class Person    
{  
    public string Name { get; set; }  
      
     [JsonIgnore]  
    public int Age { get; set; }  
}  
  
public class Program    
{  
    public static void Main()  
    {  
        Person person = new() { Name = "John", Age = 30 };  
  
        // Serialize to JSON   
        string jsonString = JsonSerializer.Serialize(person);  
        Console.WriteLine(jsonString);  
  
        // Deserialize from JSON   
        Person deserializedPerson = JsonSerializer.Deserialize\<Person>(jsonString);  
        Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");  
    }  
}
Output  
  
{"Name":"John"}  
Name: John, Age: 0

我们添加了另一个命名空间,并且只是在 serialization by attribute 中装饰了我们不需要的属性。JSON 字符串的输出将不带属性。请注意,反序列化指示为 0,这是因为 type 的默认值。System.Text.Json.Serialization[JsonIgnore]AgeAge int

这对于敏感、与某些操作无关或在对象的 JSON 表示形式中冗余的属性特别有用。

部分 JSON 读取

假设我们从 API 响应中收到一个字符串,该字符串表示非常大且复杂的 JSON 对象,但是,我们只需要它的一部分。以下是我们如何实现它:

using System;  
using System.Text.Json;  
  
public class Program    
{  
    public static void Main()  
    {  
        string jsonString = @"{  
 ""FirstName"": ""John"",  
 ""LastName"": ""Doe"",  
 ""Age"": 30,  
 ""Email"": ""john.doe@example.com"",  
 ""Address"": {  
 ""Street"": ""123 Main St"",  
 ""City"": ""Anytown"",  
 ""ZipCode"": ""12345""  
 }  
 }";  
  
        // Parse the JSON string using JsonDocument   
        using (JsonDocument document = JsonDocument.Parse(jsonString))  
        {  
            // Access the root element   
            JsonElement root = document.RootElement;  
  
            // Read properties   
            string firstName = root.GetProperty("FirstName").GetString();  
            string lastName = root.GetProperty("LastName").GetString();  
            int age = root.GetProperty("Age").GetInt32();  
            string email = root.GetProperty("Email").GetString();  
  
            // Access nested object   
            JsonElement address = root.GetProperty("Address");  
            string street = address.GetProperty("Street").GetString();  
            string city = address.GetProperty("City").GetString();  
            string zipCode = address.GetProperty("ZipCode").GetString();  
  
            // Print out the values   
            Console.WriteLine("Person Details:");  
            Console.WriteLine($"FirstName: {firstName}");  
            Console.WriteLine($"LastName: {lastName}");  
            Console.WriteLine($"Age: {age}");  
            Console.WriteLine($"Email: {email}");  
            Console.WriteLine("Address:");  
            Console.WriteLine($"Street: {street}");  
            Console.WriteLine($"City: {city}");  
            Console.WriteLine($"ZipCode: {zipCode}");  
        }  
    }  
}

Output

Person Details:  
FirstName: John  
LastName: Doe  
Age: 30  
Email: john.doe@example.com  
Address:  
Street: 123 Main St  
City: Anytown  
ZipCode: 12345

在上面的示例中,我们接收用户详细信息,包括他的地址。如果我们必须将其转换为真正的 C# 对象,我们必须定义 C# 类并使用反序列化,但是,如果目的是只获取某些部分而无需创建 C# 类,那么我们可以使用 method 来实现。它接受 JSON 字符串并返回 object。使用 我们可以进一步获得它的 inner properties。JsonDocument.ParseJsonDocumentJsonDocument

流媒体支持

类 in 允许您以流式处理方式写入 JSON 数据,这对于生成大型 JSON 文档或需要增量 JSON 写入的场景非常有用。Utf8JsonWriterSystem.Text.Json

在这里,我们将创建一个简单的示例,其中有一个表示 people 的对象列表,我们使用它来生成 JSON 输出。Utf8JsonWriter

using System;  
using System.Collections.Generic;  
using System.IO;  
using System.Text;  
using System.Text.Json;  
  
public class Person    
{  
    public string FirstName { get; set; }  
    public string LastName { get; set; }  
    public int Age { get; set; }  
    public string Email { get; set; }  
}  
  
public class Program    
{  
    public static void Main()  
    {  
        var people = new List<Person>  
        {  
            new Person { FirstName = "John", LastName = "Doe", Age = 30, Email = "john.doe@example.com" },  
            new Person { FirstName = "Jane", LastName = "Smith", Age = 25, Email = "jane.smith@example.com" },  
            new Person { FirstName = "Michael", LastName = "Johnson", Age = 45, Email = "michael.johnson@example.com" },  
        };  
  
        using (var stream = new MemoryStream())  
        using (var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true }))  
        {  
            writer.WriteStartArray();  
  
            foreach (var person in people)  
            {  
                writer.WriteStartObject();  
                writer.WriteString("FirstName", person.FirstName);  
                writer.WriteString("LastName", person.LastName);  
                writer.WriteNumber("Age", person.Age);  
                writer.WriteString("Email", person.Email);  
                writer.WriteEndObject();  
            }  
  
            writer.WriteEndArray();  
            writer.Flush();  
  
            string jsonString = Encoding.UTF8.GetString(stream.ToArray());  
            Console.WriteLine("Generated JSON:");  
            Console.WriteLine(jsonString);  
        }  
    }  
}

Output

Generated JSON:  
[  
  {  
    "FirstName": "John",  
    "LastName": "Doe",  
    "Age": 30,  
    "Email": "john.doe@example.com"  
  },  
  {  
    "FirstName": "Jane",  
    "LastName": "Smith",  
    "Age": 25,  
    "Email": "jane.smith@example.com"  
  },  
  {  
    "FirstName": "Michael",  
    "LastName": "Johnson",  
    "Age": 45,  
    "Email": "michael.johnson@example.com"  
  }  
]

使用 允许您高效且增量地生成 JSON 数据。上面的示例显示了如何将对象列表写入 JSON 数组,确保每个对象的属性都以流式方式序列化。此方法对于大型数据集或需要高性能和低内存开销的应用程序特别有用。Utf8JsonWriter

JSON 是数据交换的全球标准,在很多情况下都需要在 JSON 和 C# 之间进行处理。本文几乎没有触及所提供的功能的表面。还有很多其他功能值得一试。如果您的程序正在处理大量的 JSON 和 C# 对象,那么建议花一些时间了解此命名空间类提供的功能。

阅读排行