C# 优雅高效地处理Json数据

JSON(JavaScript Object Notation)已成为现代Web应用和API开发中最常用的数据交换格式。C#提供了多种处理JSON的方式,从基础的字符串操作到强大的序列化库。本文将介绍如何在C#中优雅高效地处理JSON数据。

一、.NET中的JSON处理基础

1.1 JSON基础知识回顾

JSON由以下几种基本结构组成:

  • 键值对集合(对象):{"name": "John", "age": 30}
  • 值的有序列表(数组):[1, 2, 3, 4, 5]
  • 基本数据类型:字符串、数字、布尔值、null

1.2 .NET中的JSON处理方式

.NET提供了多种处理JSON的方式:

  1. System.Text.Json - .NET Core 3.0+引入的高性能JSON库
  2. Newtonsoft.Json(Json.NET) - 最流行的第三方JSON库

二、使用System.Text.Json处理JSON

System.Text.Json是.NET Core 3.0及更高版本中的内置JSON库,性能优异且无需额外依赖。

2.1 基本序列化与反序列化

using System;
using System.Text.Json;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public DateTime BirthDate { get; set; }
}

class Program
{
    static void Main()
    {
        // 创建对象
        var person = new Person
        {
            Name = "张三",
            Age = 30,
            BirthDate = new DateTime(1990, 1, 1)
        };

        // 序列化为JSON字符串
        string jsonString = JsonSerializer.Serialize(person);
        Console.WriteLine(jsonString);

        // 反序列化JSON字符串为对象
        var deserializedPerson = JsonSerializer.Deserialize<Person>(jsonString);
        Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");
    }
}

2.2 自定义序列化选项

// 配置序列化选项
var options = new JsonSerializerOptions
{
    WriteIndented = true, // 美化输出
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase, // 属性名使用驼峰命名
    Converters = { new DateTimeConverterUsingDateTimeParse() } // 自定义转换器
};

// 使用配置的选项进行序列化
string jsonString = JsonSerializer.Serialize(person, options);

2.3 处理复杂类型

public class Company
{
    public string Name { get; set; }
    public List<Employee> Employees { get; set; }
}

public class Employee
{
    public string Name { get; set; }
    public decimal Salary { get; set; }
}

// 序列化复杂对象
var company = new Company
{
    Name = "微软",
    Employees = new List<Employee>
    {
        new Employee { Name = "张三", Salary = 50000 },
        new Employee { Name = "李四", Salary = 60000 }
    }
};

string companyJson = JsonSerializer.Serialize(company, options);
Console.WriteLine(companyJson);

// 反序列化复杂对象
var deserializedCompany = JsonSerializer.Deserialize<Company>(companyJson);

三、使用Newtonsoft.Json(Json.NET)处理JSON

Newtonsoft.Json是.NET生态中最流行的JSON库,功能强大且灵活。

3.1 安装Newtonsoft.Json

通过NuGet安装:

Install-Package Newtonsoft.Json

3.2 基本序列化与反序列化

using Newtonsoft.Json;

// 序列化
string jsonString = JsonConvert.SerializeObject(person);
Console.WriteLine(jsonString);

// 反序列化
var deserializedPerson = JsonConvert.DeserializeObject<Person>(jsonString);
Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");

3.3 高级特性

3.3.1 自定义转换器
public class DateTimeConverter : JsonConverter<DateTime>
{
    public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        return DateTime.ParseExact(reader.Value.ToString(), "yyyy-MM-dd", CultureInfo.InvariantCulture);
    }

    public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString("yyyy-MM-dd"));
    }
}

// 使用自定义转换器
var settings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new DateTimeConverter() }
};

string jsonString = JsonConvert.SerializeObject(person, settings);

3.3.2 处理动态JSON
// 动态解析JSON
string dynamicJson = @"{""name"":""张三"",""age"":30}";
dynamic personDynamic = JsonConvert.DeserializeObject<dynamic>(dynamicJson);
Console.WriteLine($"Name: {personDynamic.name}, Age: {personDynamic.age}");

// 使用JObject
JObject jObject = JObject.Parse(dynamicJson);
string name = (string)jObject["name"];
int age = (int)jObject["age"];

3.3.3 处理JSON数组
string jsonArray = @"[
    {""name"":""张三"",""age"":30},
    {""name"":""李四"",""age"":25}
]";

List<Person> people = JsonConvert.DeserializeObject<List<Person>>(jsonArray);
foreach (var person in people)
{
    Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
}

四、性能优化技巧

4.1 选择合适的库

  • ​System.Text.Json​​:性能最佳,适合高性能场景
  • ​Newtonsoft.Json​​:功能最丰富,适合复杂场景

4.2 重用序列化设置

// 创建一次并重用
private static readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
{
    WriteIndented = true,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};

// 使用时直接传入
string jsonString = JsonSerializer.Serialize(person, _jsonOptions);

4.3 流式处理大JSON

对于大JSON文件,使用流式API避免内存问题:

// 使用System.Text.Json流式读取
using (FileStream fs = File.OpenRead("large.json"))
using (JsonDocument doc = JsonDocument.Parse(fs))
{
    JsonElement root = doc.RootElement;
    // 处理JSON数据
}

// 使用Newtonsoft.Json流式读取
using (StreamReader sr = new StreamReader("large.json"))
using (JsonTextReader reader = new JsonTextReader(sr))
{
    while (reader.Read())
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            // 处理对象
        }
    }
}

4.4 避免频繁分配

// 不好的做法 - 每次创建新选项
for (int i = 0; i < 1000; i++)
{
    var options = new JsonSerializerOptions();
    JsonSerializer.Serialize(person, options);
}

// 好的做法 - 重用选项
var options = new JsonSerializerOptions();
for (int i = 0; i < 1000; i++)
{
    JsonSerializer.Serialize(person, options);
}

五、实际应用示例

5.1 API响应处理

// 使用System.Text.Json处理API响应
public async Task<User> GetUserAsync(int userId)
{
    using HttpClient client = new HttpClient();
    string url = $"https://api.example.com/users/{userId}";
    HttpResponseMessage response = await client.GetAsync(url);
    response.EnsureSuccessStatusCode();
    
    string jsonString = await response.Content.ReadAsStringAsync();
    return JsonSerializer.Deserialize<User>(jsonString, _jsonOptions);
}

// 使用Newtonsoft.Json处理API响应
public async Task<User> GetUserAsync(int userId)
{
    using HttpClient client = new HttpClient();
    string url = $"https://api.example.com/users/{userId}";
    HttpResponseMessage response = await client.GetAsync(url);
    response.EnsureSuccessStatusCode();
    
    string jsonString = await response.Content.ReadAsStringAsync();
    return JsonConvert.DeserializeObject<User>(jsonString, _settings);
}

5.2 配置文件处理

// 读取JSON配置文件
public class AppConfig
{
    public string ConnectionString { get; set; }
    public int Timeout { get; set; }
    public List<string> AllowedOrigins { get; set; }
}

public AppConfig LoadConfig(string path)
{
    string json = File.ReadAllText(path);
    return JsonSerializer.Deserialize<AppConfig>(json, _jsonOptions);
    // 或使用Newtonsoft.Json: return JsonConvert.DeserializeObject<AppConfig>(json, _settings);
}

// 保存JSON配置文件
public void SaveConfig(AppConfig config, string path)
{
    string json = JsonSerializer.Serialize(config, _jsonOptions);
    File.WriteAllText(path, json);
    // 或使用Newtonsoft.Json: File.WriteAllText(path, JsonConvert.SerializeObject(config, _settings));
}

5.3 动态数据交换

// 处理动态JSON数据
public void ProcessDynamicData(string json)
{
    // 使用System.Text.Json
    JsonDocument doc = JsonDocument.Parse(json);
    JsonElement root = doc.RootElement;
    
    if (root.TryGetProperty("name", out JsonElement nameElement))
    {
        string name = nameElement.GetString();
        // 处理name
    }
    
    // 使用Newtonsoft.Json
    dynamic data = JsonConvert.DeserializeObject<dynamic>(json);
    string name = data.name;
    // 处理name
}

  1. ​选择合适的库​​:

    • 新项目优先使用System.Text.Json
    • 需要高级功能或迁移现有代码使用Newtonsoft.Json
  2. ​性能优化​​:

    • 重用序列化设置
    • 对于大JSON使用流式API
    • 避免不必要的分配
  3. ​错误处理​​:

    • 总是处理可能的JSON解析异常
    • 验证输入JSON的结构
  4. ​代码组织​​:

    • 为复杂类型创建专门的DTO(数据传输对象)
    • 使用自定义转换器处理特殊格式
  5. ​安全性​​:

    • 反序列化时验证数据
    • 限制最大JSON大小防止DoS攻击

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code_shenbing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值