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

直接用 JsonSerializer.Serialize 或 JsonConvert.SerializeObject 就能序列化,但出问题往往不是“不会调”,而是类型、配置、时区、大小写这些细节没对上。
System.Text.Json 默认驼峰命名导致字段名被改写
你定义了 public string UserName { get; set; },序列化后却变成 "userName" —— 这不是 bug,是 JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase 在起作用(.NET 6+ 新增的默认行为,尤其在 ASP.NET Core Web API 中自动启用)。
- 确认是否真需要驼峰:如果是内部系统或对接前端,大概率要;如果是和 Java/Python 服务互通,对方可能期望 PascalCase,那就得关掉
- 关掉方式:
var options = new JsonSerializerOptions { PropertyNamingPolicy = null }; - 注意:这个设置只影响 public 属性名,不影响字典 key(除非你用的是 .NET 7+ 并显式设置了
DictionaryKeyPolicy) - 别混淆
PropertyName和JsonPropertyName特性:前者是全局策略,后者是单个属性覆盖,优先级更高
Newtonsoft.Json 序列化 DateTime 输出 /Date(1234567890000)/ 格式
这是 Newtonsoft 默认用 JavaScriptDateTimeConverter 的结果,现代 API 基本不认这种格式,解析会失败或时间错乱。
- 强制改用 ISO 格式:
new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.IsoDateFormat } - 如果服务端要求 UTC 时间,别只靠配置,务必在序列化前调用
.ToUniversalTime(),否则本地时区时间会被当成 UTC 写入 - 自定义格式更稳妥:
DateFormatString = "yyyy-MM-dd HH:mm:ss",但要注意它只在DateFormatHandling = DateFormatHandling.Custom下生效 - 别在属性上堆
[JsonConverter(typeof(DateTimeConverter))]又在全局再配一遍,容易冲突
序列化 Dictionary 后键名丢失或全小写
不是数据丢了,是库的默认策略在“动”你的 key。System.Text.Json 默认保留字典键原样;Newtonsoft.Json 则受 ContractResolver 影响极大。
- Newtonsoft 中检查是否用了
CamelCasePropertyNamesContractResolver—— 它不仅改属性名,也改字典 key - 想锁死原始键名:
new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() } - System.Text.Json 在 .NET 6+ 后,若启用了
PropertyNamingPolicy,字典 key 也会被改(此前版本不会),这点极易忽略 - 如果 value 是匿名对象或
JObject,确保它本身没被二次序列化——常见于嵌套调用JsonConvert.SerializeObject(new { data = JObject.Parse(json) })
序列化 long 类型 ID 到前端时精度丢失
JavaScript 的 Number 最大安全整数是 2^53 - 1,而 C# 的 long 能到 2^63 - 1,雪花 ID 等典型场景一传就变零头。
- 必须把 long 转成字符串再序列化,不能靠前端 parseInt 补救
- Newtonsoft 推荐写自定义转换器:
public class LongToStringConverter : JsonConverter,重写Write方法输出writer.WriteStringValue(value.ToString()) - System.Text.Json 用法类似,但需继承
JsonConverter,并在options.Converters.Add(new LongToStringConverter())注册 - 别试图用
ToString("D")或其它格式化,只要最终是字符串类型,前端就能无损接收
最常被跳过的其实是 JSON 校验环节:序列化后别直接发,先用 JsonDocument.Parse(json) 或在线工具过一遍,很多“序列化失败”其实是上游拼错了字符串,不是序列化逻辑的问题。











