You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

System.Text.Json反序列化含NodaTime属性的JSON时全为默认值

问题根因

核心问题和NodaTime配置无关,是System.Text.Json 默认严格区分属性名大小写导致的:

  • 你的接口返回的JSON字段为小驼峰格式(id/code/interval等),但C#实体类属性为大驼峰命名(Id/Code/Interval等)。
  • 你手动实例化的JsonSerializerOptions既没有开启大小写不敏感匹配,也没有配置驼峰命名映射规则,System.Text.Json找不到任何和JSON key匹配的属性,就会给所有属性赋默认值,这也是你移除NodaTime配置后依然得到全默认值对象的原因。
  • Newtonsoft.Json能正常解析的原因很简单:它默认采用大小写不敏感的属性匹配规则,不需要额外配置就能自动对应大小驼峰的字段名。

额外注意一个配置误区:你在AddControllers().AddJsonOptions()中配置的序列化选项,仅对Controller自身处理请求、响应的逻辑生效,不会自动作用于你手动调用JsonSerializer.Deserialize、HttpClient.ReadFromJsonAsync的场景,这类场景必须手动传入配置一致的选项。

修复方案
  1. 构造反序列化使用的JsonSerializerOptions时,开启属性名大小写不敏感匹配,同时保留NodaTime配置即可:
var jsonOptions = new JsonSerializerOptions()
    .ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
// 开启大小写不敏感匹配,适配小驼峰JSON字段与大驼峰C#属性
jsonOptions.PropertyNameCaseInsensitive = true;
// 如果需要保留原枚举转换配置,也可以加上这行
jsonOptions.Converters.Add(new JsonStringEnumConverter());

var result = await getResponse.Content.ReadFromJsonAsync<MyContract>(jsonOptions);
  1. 如果你需要严格匹配大小写(性能略高),也可以显式指定驼峰命名策略,和服务端序列化输出的规则完全对齐:
var jsonOptions = new JsonSerializerOptions()
    .ConfigureForNodaTime(DateTimeZoneProviders.Tzdb)
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    Converters = { new JsonStringEnumConverter() }
};
  1. 为了避免服务端、客户端序列化配置不一致,建议把NodaTime、枚举转换、命名规则这类公共配置抽成全局静态单例,服务端配置Controller和客户端反序列化时统一使用该单例,不要每次零散手动new选项。

配置完成后,JSON中的P90D字符串会被NodaTime自带的JSON转换器正常反序列化为Period类型对象(对应90天的时间间隔),其余属性也会正常映射为预期值。

内容的提问来源于stack exchange,提问作者span

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 19:42:23