游乐游手机版
首页/编程语言/文章详情

C# JSON序列化完整指南与常见问题解决方法

时间:2026-05-06 20:31
C JSON序列化:那些看似“玄学”的问题,其实都有章可循 在C 里处理JSON,JsonSerializer Serialize 或 JsonConvert SerializeObject 这两行代码谁都会写。但真正让人头疼的,往往不是“怎么调”,而是那些藏在类型、配置、时区、命名规则里的细节。

C# JSON序列化:那些看似“玄学”的问题,其实都有章可循

c#如何序列化JSON_c#序列化JSON常见问题与排错指南

在C#里处理JSON,JsonSerializer.SerializeJsonConvert.SerializeObject 这两行代码谁都会写。但真正让人头疼的,往往不是“怎么调”,而是那些藏在类型、配置、时区、命名规则里的细节。它们一旦对不上,轻则字段错位,重则数据丢失。下面这四大高频问题,几乎每个.NET开发者都会踩到。

System.Text.Json 默认驼峰命名、Newtonsoft.DateTime格式异常、字典键被改、long精度丢失是四大高频问题;需分别通过设置PropertyNamingPolicy=null、DateFormatHandling.IsoDateFormat、DefaultContractResolver、long转字符串解决。

System.Text.Json 默认驼峰命名导致字段名被改写

你有没有遇到过这种情况:明明在C#里定义的是 public string UserName { get; set; },序列化出去却变成了 "userName"?先别急着怀疑人生,这通常不是bug,而是特性在起作用。

从.NET 6开始,System.Text.Json 默认启用了 JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase。这个策略尤其在ASP.NET Core Web API中会自动生效,目的是为了迎合前端Ja vaScript社区的命名习惯。

  • 先确认需求:如果你的服务是内部系统,或者主要对接前端,用驼峰命名大概率没问题。但如果是和Ja va、Python等其他后端服务互通,对方很可能期望的是PascalCase(即首字母大写),这时就需要关掉它。
  • 如何关掉:很简单,var options = new JsonSerializerOptions { PropertyNamingPolicy = null }; 就能让命名策略失效。
  • 注意边界:这个设置只影响类的public属性名,默认不影响字典的key。除非你用的是.NET 7及以上版本,并且显式设置了 DictionaryKeyPolicy
  • 别混淆了:全局的 PropertyNamingPolicy 和单个属性上的 [JsonPropertyName("CustomName")] 特性是两回事。后者的优先级更高,可以覆盖全局策略。

Newtonsoft.Json 序列化 DateTime 输出 /Date(1234567890000)/ 格式

如果你还在用Newtonsoft.Json(即Json.NET),可能会发现序列化出来的时间戳长这样:/Date(1234567890000)/。这是库默认使用 Ja vaScriptDateTimeConverter 的结果,一种比较古老的格式。现代的API接口基本已经不认这种格式了,前端解析时要么失败,要么时间错乱。

  • 强制使用ISO标准格式:最直接的解决方法是配置序列化设置:new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.IsoDateFormat }。这样输出的就是 "2023-10-27T10:30:00Z" 这种通用格式。
  • 时区问题不能只靠配置:如果服务端明确要求UTC时间,千万别只依赖这个配置。务必在序列化前,对DateTime对象调用 .ToUniversalTime()。否则,本地时区的时间会被直接当成UTC时间写进去,造成误解。
  • 自定义格式更稳妥:对于有固定格式要求的场景,可以设置 DateFormatString = "yyyy-MM-dd HH:mm:ss"。但要注意,这个设置只在 DateFormatHandling = DateFormatHandling.Custom 时才会生效。
  • 避免配置冲突:别在同一个属性的头上既标记了 [JsonConverter(typeof(DateTimeConverter))],又在全局配置里配一遍,这样很容易导致行为不一致。

序列化 Dictionary 后键名丢失或全小写

字典序列化后,发现key的名字变了,甚至全变成小写了?别慌,数据没丢,是序列化库的默认策略在“动”你的key。

这里有个关键区别:System.Text.Json 默认会保留字典键的原样;而 Newtonsoft.Json 的行为则严重受 ContractResolver 影响。

  • 检查Newtonsoft的解析器:如果你用了 CamelCasePropertyNamesContractResolver,那要注意了,它不仅会把属性名改成驼峰,字典的key也会被一并改造。
  • 锁死原始键名:在Newtonsoft中,想保持key不变,可以使用默认的解析器:new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() }
  • System.Text.Json的版本陷阱:在.NET 6及以后版本,如果你启用了全局的 PropertyNamingPolicy(比如驼峰),那么字典的key也会被影响而改变。这一点在早期版本中是不会发生的,非常容易忽略。
  • 警惕嵌套序列化:如果字典的value是匿名对象或者动态的 JObject,要确保它本身没有被二次序列化。一个常见的坑是:JsonConvert.SerializeObject(new { data = JObject.Parse(json) }),里面的JObject可能已经被处理过一次了。

序列化 long 类型 ID 到前端时精度丢失

这是前后端联调时的一个经典“惨案”。C#里的 long 类型(Int64)最大值可以达到 2^63 - 1,常用于生成雪花ID等大数字。但Ja vaScript的 Number 类型,其最大安全整数是 2^53 - 1。一旦超过这个范围,数字传到前端就会精度丢失,变成一串奇怪的尾数。

  • 根本解法:转成字符串:必须把long类型的值,在序列化阶段就转换成字符串。不要指望前端用 parseInt 去补救,那为时已晚。
  • Newtonsoft的解决方案:推荐编写一个自定义转换器。继承 JsonConverter,然后重写 WriteJson 方法,在里面调用 writer.WriteValue(value.ToString()) 即可。
  • System.Text.Json的解决方案:思路类似,继承 JsonConverter,实现对应的 Write 方法。最后记得在 JsonSerializerOptions 里通过 options.Converters.Add(new LongToStringConverter()) 注册这个转换器。
  • 格式化不是关键:别纠结于用 ToString("D") 还是其他数字格式,只要最终输出的JSON值是带引号的字符串(如 "id": "1234567890123456789"),前端就能无损接收。

最后,还有一个最常被跳过的环节:序列化后的校验。代码跑通了,不代表JSON就对了。在把数据发出去之前,不妨先用 JsonDocument.Parse(json) 快速验证一下结构,或者扔到在线JSON格式化工具里看一眼。很多时候所谓的“序列化失败”,其实是上游数据拼接时字符串就错了,问题根本不在序列化逻辑本身。

来源:https://www.php.cn/faq/2324543.html
上一篇C# GDI+绘图完整教程从入门到精通实战指南 下一篇C#跨线程安全访问WinForm控件使用Invoke方法详解
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
CentOS与Golang打包常见兼容性问题探讨
编程语言 · 2026-07-01

CentOS与Golang打包常见兼容性问题探讨

CentOS与Golang打包的兼容性问题集中在glibc版本不匹配、交叉编译环境变量错误、依赖库缺失及Go依赖管理不规范。可通过Docker容器编译、选择兼容Go版本、正确设置GOOS GOARCH环境变量、安装对应开发包及使用GoModules解决。

CentOS中Fortran与Python如何协同工作从入门到实战完整教程
编程语言 · 2026-07-01

CentOS中Fortran与Python如何协同工作从入门到实战完整教程

在CentOS中,Fortran与Python可通过f2py、SWIG、共享库调用或subprocess协同。f2py封装Fortran为Python模块,支持数组运算;共享库需手动对齐数据类型;系统调用适合独立计算。

CentOS中Golang打包优化方法
编程语言 · 2026-07-01

CentOS中Golang打包优化方法

在CentOS中优化Golang编译打包,可显著提升编译速度并减小二进制文件体积。关键技巧包括:设置环境变量、使用Go模块管理依赖、编译时添加-ldflags= "-s-w "去除调试信息、利用UPX工具压缩、运行strip清理符号表,以及优化cgo内C代码的编译选项。综合运用这些方法能有效优化最终程序。

在CentOS系统中cpustat与其他工具协同使用的完整方法
编程语言 · 2026-07-01

在CentOS系统中cpustat与其他工具协同使用的完整方法

cpustat作为sysstat包的CPU监控工具,可通过管道与grep等命令配合过滤数据,利用脚本自动记录带时间戳的日志,或结合图形工具查看,也可格式化输出后接入Zabbix、Grafana等Web监控系统,实现可视化与告警。

CentOS中readdir与其他Linux发行版的差异
编程语言 · 2026-07-01

CentOS中readdir与其他Linux发行版的差异

CentOS基于RHEL,与Ubuntu、Debian、Fedora在包管理器(yum dnfvsapt)、默认文件系统(XFSvsext4)等存在差异,但readdir等系统调用遵循POSIX标准,行为一致。