导读:本期聚焦于蚂蚁创作的《C#怎么将对象序列化为JSON?System.Text.Json使用方法详解》,敬请观看详情。C#中将对象序列化为JSON是日常开发中的高频需求。本文围绕.NET官方推荐的System.Text.Json库展开,从最基础的JsonSerializer.Serialize与Deserialize用法讲起,逐步覆盖属性命名控制、忽略空值、枚举与日期格式处理、中文乱码解决、流式序列化大对象等进阶技巧,并对比Newtonsoft.Json的差异与迁移注意事项。文中的示例代码均基于.NET 6及以上版本编写,复制即可运行,帮助你快速掌握高性能的JSON处理方案,避开常见的编码与反序列化陷阱。

在C#开发中,对象与JSON字符串之间的转换几乎是绕不开的操作,无论是编写Web API接口、读取配置文件,还是与第三方系统通信,都需要用到序列化与反序列化。自.NET Core 3.0开始,微软推出了官方的System.Text.Json库,它凭借更高的性能和更低的内存占用,逐渐取代了传统的Newtonsoft.Json(Json.NET),成为.NET平台默认的JSON处理方案。本文将系统讲解System.Text.Json的核心用法和常见配置技巧,帮助你快速上手并避开典型陷阱。

C#怎么将对象序列化为JSON?System.Text.Json使用方法详解

一、基础用法:序列化与反序列化

System.Text.Json的核心类是JsonSerializer,它提供了静态方法SerializeDeserialize来完成对象与JSON字符串的互转。使用前需要引入命名空间System.Text.Json。先定义一个简单的实体类:

using System;
using System.Text.Json;

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

class Program
{
    static void Main()
    {
        var person = new Person { Name = "张三", Age = 28, Email = "zhangsan@ipipp.com" };

        // 序列化:对象转JSON字符串
        string json = JsonSerializer.Serialize(person);
        Console.WriteLine(json);

        // 反序列化:JSON字符串转对象
        Person result = JsonSerializer.Deserialize<Person>(json);
        Console.WriteLine(result.Name);
    }
}

上面的代码输出结果为{"Name":"张三","Age":28,"Email":"zhangsan@ipipp.com"}。可以看到默认情况下属性名保持PascalCase原样输出,不会像Newtonsoft.Json那样有驼峰转换,这一点在迁移老项目时要特别注意。

反序列化时需要注意,目标类必须有公共的无参构造函数(或者使用[JsonConstructor]标注带参构造函数),属性也必须是可写的。如果JSON中存在目标类没有的属性,默认不会报错而是直接忽略;反过来,如果目标类的必填属性在JSON中缺失,默认也不会抛异常,会保留默认值。如果希望严格校验,可以设置JsonUnmappedMemberHandling.Disallow或使用required关键字配合.NET 8的严格模式。

二、常用序列化配置选项

直接调用Serialize的重载虽然简单,但实际项目中往往需要自定义输出格式,比如驼峰命名、缩进美化、忽略空值等。这就需要用到JsonSerializerOptions

var options = new JsonSerializerOptions
{
    // 属性名转为驼峰命名
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    // 输出缩进格式化的JSON,便于阅读
    WriteIndented = true,
    // 忽略值为null的属性
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    // 忽略只读属性
    IgnoreReadOnlyProperties = true,
    // 枚举以字符串形式输出而非数字
    Converters = { new JsonStringEnumConverter() }
};

string json = JsonSerializer.Serialize(person, options);

配置完成后,输出会变成驼峰命名的缩进格式,null属性不再出现。这里特别提醒两点:第一,JsonStringEnumConverter非常实用,不加它时枚举会被序列化成数字,前端拿到12这样的值很难理解;第二,如果序列化中文后出现类似\u5F20\u4E09的转义序列,这是默认编码器出于安全考虑的结果,可以设置Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping来让中文直接输出,但要确认下游消费方能正确处理非ASCII字符。

关于选项对象的复用也有讲究。JsonSerializerOptions内部会缓存序列化元数据,重复new一个新实例会导致缓存无法命中,性能明显下降。官方建议将配置好的options声明为单例或静态字段复用,例如JsonSerializerOptions.Web就是一个内置的常用Web默认配置。此外,也可以通过特性精细控制单个属性,例如[JsonPropertyName("user_name")]指定JSON字段名,[JsonIgnore]排除某个属性。

三、处理循环引用与复杂类型

实体之间存在双向导航关系时(比如订单引用客户、客户又包含订单列表),直接序列化会抛出JsonException,提示检测到循环引用。解决方式是开启引用处理:

var options = new JsonSerializerOptions
{
    ReferenceHandler = ReferenceHandler.Preserve
};

// 输出的JSON会带 $id 和 $ref 元数据来保持对象关系
string json = JsonSerializer.Serialize(order, options);

ReferenceHandler.Preserve会在JSON中写入$id$ref元数据来打破循环,反序列化时也能还原对象图。这种方式虽然解决了问题,但生成的JSON不是标准格式,如果JSON要给第三方系统消费,更推荐的做法是使用DTO(数据传输对象)切断循环引用,或者在导航属性上加[JsonIgnore]

对于字典类型,默认要求键为字符串。如果键是int或枚举,.NET 7之前需要自定义转换器,之后版本已原生支持非字符串键的字典序列化。日期类型方面,DateTime默认输出ISO 8601格式(如2024-01-15T10:30:00),如需自定义格式可以注册自定义的JsonConverter。多态序列化则需要配合[JsonDerivedType]特性,在基类上声明所有派生类型,否则派生类的特有属性会丢失。

四、性能进阶:流式与异步操作

处理大对象或高频调用场景时,字符串方式的序列化会产生大量临时字符串分配,给GC带来压力。System.Text.Json提供了基于Utf8BufferWriter和流的API来缓解这个问题:

using System.Text.Json;

// 将对象直接写入文件流,避免生成超大字符串
using (var fs = File.Create("data.json"))
{
    await JsonSerializer.SerializeAsync(fs, bigOrderList, options);
}

// 从文件流异步读取并反序列化
using (var fs = File.OpenRead("data.json"))
{
    var list = await JsonSerializer.DeserializeAsync<List<Order>>(fs, options);
}

流式API直接操作UTF-8字节,省去了字符串编码转换的中间环节,官方基准测试显示其吞吐量比Newtonsoft.Json高出数倍,内存分配也大幅减少。对于超大JSON文档,还可以使用JsonDocument做只读解析,或用Utf8JsonReader/Utf8JsonWriter进行底层高性能读写,不过这两个API使用门槛较高,一般情况下用JsonSerializer的流式重载已经足够。

迁移方面,如果项目原本使用Newtonsoft.Json,主要差异包括:默认命名策略不同、大小写敏感的反序列化匹配、日期格式处理、JsonPropertyName替代JsonProperty等。微软提供了System.Text.Json的兼容包可以弥补部分功能差距,但建议新项目直接采用原生API,遵循官方最佳实践,既能获得性能收益,也能减少依赖。

总结一下,System.Text.Json的入门门槛并不高,掌握JsonSerializer的几个核心重载和JsonSerializerOptions的常用配置,就能覆盖绝大多数业务场景。重点记住三件事:复用options实例提升性能、处理好中文编码与枚举格式、用流式API应对大对象,你的JSON处理代码就会既高效又健壮。

C#序列化JSONSystem.Text.JsonJsonSerializer修改时间:2026-09-01 04:34:51

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。