问题:对象转JSON,到底该用哪个库?
前几天在其中一个群里看到个挺有意思的对话:
"兄弟,你那个接口返回的JSON咋弄的?"
"就JsonConvert.SerializeObject啊,还能咋弄。"
"这不是Newtonsoft.Json吗?现在新项目不是推荐用System.Text.Json?"
"啊?这俩啥区别?我用了好几年Newtonsoft了,没出过问题啊。"
说实话,这种困惑太常见了。.NET里对象转JSON的方式确实不少,而且各有各的脾气。今天咱们就把这事捋清楚,以后别再纠结了。
结论:三种主流方式,各有各的用武之地
一句话总结:
-
System.Text.Json:.NET亲儿子,性能好,新项目首选
-
Newtonsoft.Json:老牌王者,功能全,旧项目维护离不开
-
Utf8Json:性能狂魔,追求极致速度的备选方案
下面一个一个聊,看看它们到底有啥不一样。
展开:三种方式深度对比
1. System.Text.Json:官方出品,性能担当
从.NET Core 3.0开始,微软自己搞了个JSON处理库,就是System.Text.Json。为啥要自己造轮子?因为要追求高性能、低内存占用,充分利用了Span<T>这些现代.NET特性。
基本用法:
using System.Text.Json;
var user = new { Name = "码农刚子", Age = 30, City = "北京" };
// 基础序列化string jsonString = JsonSerializer.Serialize(user);
// 带配置的序列化(格式化输出)var options = new JsonSerializerOptions { WriteIndented = true, // 格式化,更易读 PropertyNamingPolicy = JsonNamingPolicy.CamelCase // 驼峰命名};string prettyJson = JsonSerializer.Serialize(user, options);
它强在哪?
-
性能好:比Newtonsoft.Json快,内存分配少
-
零依赖:.NET Core/5+自带,不用装NuGet包
-
默认严格:属性名必须匹配,提前发现问题
它坑在哪?
-
功能相对少:有些Newtonsoft花哨的功能它没有
-
日期格式支持有限:不如Newtonsoft灵活
-
属性名默认转驼峰:以前用PascalCase的老代码要改
适用场景:
-
新项目,尤其是.NET Core 3.0+
-
追求性能的Web API
-
云原生应用,需要控制内存
2. Newtonsoft.Json(Json.NET):老牌王者,功能最全
在System.Text.Json出生之前,Newtonsoft.Json就是.NET社区的事实标准。几乎所有.NET项目都在用它,至今仍有大量项目依赖。
基本用法:
using Newtonsoft.Json;
var user = new { Name = "码农刚子", Age = 30, City = "北京" };
// 基础序列化string jsonString = JsonConvert.SerializeObject(user);
// 带配置的序列化var settings = new JsonSerializerSettings { Formatting = Formatting.Indented, // 格式化 ReferenceLoopHandling = ReferenceLoopHandling.Ignore // 忽略循环引用};string complexJson = JsonConvert.SerializeObject(user, settings);
它强在哪?
-
功能极其丰富:循环引用处理、自定义转换器、条件序列化...
-
容错性强:JSON格式不太规范也能处理
-
文档全、社区大:遇到问题一搜一大把
它坑在哪?
-
性能稍逊:比System.Text.Json慢一点
-
额外依赖:需要装NuGet包
-
体积较大:功能多,体积自然大
适用场景:
-
维护老项目,尤其是.NET Framework项目
-
需要复杂JSON处理的场景(循环引用、动态对象等)
-
对接的第三方接口JSON格式乱七八糟
3. Utf8Json:性能狂魔,极致追求
如果你对性能有近乎苛刻的要求,比如高频交易、游戏服务器这类场景,可以看看Utf8Json。
基本用法:
using Utf8Json;
var product = new { ID = 101, Name = "鼠标", Price = 99.9 };
// 直接序列化为二进制字节数组(最快)byte[] jsonBytes = JsonSerializer.Serialize(product);
// 转成字符串string jsonString = JsonSerializer.ToJsonString(product);
它强在哪?
-
速度极快:直接操作UTF-8字节流,跳过中间步骤
-
内存分配少:不使用反射,通过IL生成代码
-
零分配:在某些场景下能做到
它坑在哪?
-
功能有限:就是个序列化工具,别指望花哨功能
-
社区小:遇到问题不好查
-
学习成本:用法和前面两个不太一样
适用场景:
-
性能瓶颈处,局部优化
-
高频调用的小对象序列化
-
内存受限的环境
怎么选?给个实在的建议
看完了上面三种,估计有人要问:那我到底该用哪个?
我一般这么建议:
-
如果你是全新项目,用.NET Core 3.0以上:
优先用System.Text.Json。官方出品,性能好,少装一个包是一个,以后升级也省心。 -
如果你在维护老项目:
继续用Newtonsoft.Json,别折腾。老代码跑得好好的,换库容易出幺蛾子。 -
如果你的项目已经用了Newtonsoft,但想换:
建议谨慎。两个库有不少差异:
-
默认属性命名策略不同(camelCase vs 原样)
-
日期格式处理不同
-
某些高级特性不兼容
真想换,做好充分测试。
- 如果你在写性能敏感的核心代码:
可以考虑局部用Utf8Json做优化,但别整个项目都用,毕竟功能有限。
实用小技巧
给System.Text.Json配置全局选项:
// Program.cs 或 Startup.csbuilder.Services.Configure<JsonOptions>(options =>{ options.SerializerOptions.WriteIndented = true; options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;});
Newtonsoft.Json处理循环引用:
var settings = new JsonSerializerSettings{ ReferenceLoopHandling = ReferenceLoopHandling.Ignore, // 忽略循环引用 PreserveReferencesHandling = PreserveReferencesHandling.Objects // 或保留引用};var json = JsonConvert.SerializeObject(objWithCycle, settings);
性能优化小贴士:
-
重复序列化相同对象,考虑缓存结果
-
大JSON用流式处理,别一次全加载
-
自定义转换器处理特殊类型
总结
对象转JSON这事儿,说大不大,说小不小。选对了库,代码跑得溜;选错了,要么功能不够用,要么性能拉胯。
-
新项目:System.Text.Json
-
老项目:Newtonsoft.Json
-
极致性能:Utf8Json
记住这个原则,以后别再凭感觉选了。
我是码农刚子,如果觉得本文对你有帮助,欢迎收藏、转发、关注,让更多小伙伴少走弯路!