system.text.json序列化需显式配置选项,循环引用需加[jsonignore]或用dto解决,中文乱码、日期格式、驼峰命名等问题均需通过jsonserializeroptions定制。

直接用 JsonSerializer.Serialize() 就能转,但不配选项、不看类型、不处理边界,90% 的报错和乱码都出在这三步上。
System.Text.Json.Serialize() 报 InvalidOperationException: A possible object cycle was detected 怎么办
这是最常卡住人的错误,不是你代码写错了,是对象图里存在循环引用(比如 User 有 Posts,Post 又反向持有 User)。
-
System.Text.Json默认禁止循环,且没有ReferenceLoopHandling.Ignore这种“绕过去”的开关 - 别试
PreserveReferencesHandling——它根本不存在于当前版本(.NET 5+) - 临时解法:在引发循环的属性上加
[JsonIgnore],或设DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull并确保该属性为null - 长期解法:用 DTO 剥离关系,只序列化需要的数据字段,而不是把 EF 实体原样扔进去
中文变成 \u4f60\u597d、日期格式不对、属性名被驼峰了怎么办
默认行为不是 bug,是设计选择;要改就得显式配置 JsonSerializerOptions。
- 中文变 Unicode:传入
new JsonSerializerOptions { Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping } - 日期输出为
"2026-05-08T14:24:00+08:00"是 ISO 8601 标准,若需"2026-05-08",得注册自定义JsonConverter<datetime></datetime>或用JsonStringEnumConverter配合字符串属性 - 属性名从
UserName变成userName:是因为默认启用了JsonNamingPolicy.CamelCase,设PropertyNamingPolicy = null即可保留 Pascal 命名 - 空字符串
""被跳过?检查是否误设了DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull——它不忽略空字符串,只忽略null;要跳过空值得自己写 converter
Newtonsoft.Json 还能不能用?什么时候必须换
能用,但不是所有场景都推荐继续用。
- 还在 .NET Framework 4.x 或依赖大量
[JsonProperty("xxx")]、运行时动态 ignore 字段逻辑的项目,Newtonsoft.Json 更省事 - 已升级到 .NET 5+ 且没强依赖第三方 converter,新代码建议统一用
System.Text.Json,避免包冲突和维护双套序列化逻辑 - 迁移时注意特性名变更:
[JsonProperty("name")]→[JsonPropertyName("name")],[JsonConverter(typeof(MyConverter))]→ 写法类似但命名空间不同,且 converter 接口签名有差异 - 如果混用两个库(比如部分旧模块用 Newtonsoft,新模块用 STJ),务必确认同一对象不会被两种序列化器交替处理,否则字段可见性、null 处理策略不一致会导致静默数据丢失
真正难的不是调用那一行代码,而是判断该不该序列化那个属性、那个时间字段要不要带时区、那个字典的 key 是不是 string 类型——这些细节不提前查清,等接口返回空或乱码再回头找,花的时间远超写配置本身。











