.net默认用iso 8601格式(含t分隔符)序列化datetime,如"2024-05-20t14:30:00";若需空格分隔格式"2024-05-20 14:30:00",应通过jsonserializeroptions或jsonserializersettings自定义datetime格式,推荐按接口粒度配置而非全局修改。

为什么 DateTime 序列化出来是 "2024-05-20T14:30:00"?
这是 .NET 默认使用 ISO 8601 格式(含 T 分隔符)序列化 DateTime 的行为,System.Text.Json 和 Newtonsoft.Json 都默认如此。它本身合法、可解析、时区明确,但前端或老旧系统可能只认 "2024-05-20 14:30:00" 这种空格分隔格式,硬改前端容易出错,得在 C# 层统一处理。
用 JsonSerializerOptions 自定义 DateTime 格式(.NET 5+ 推荐)
别动模型类,直接改序列化器配置。关键不是“禁用 T”,而是指定你想要的 DateTime 字符串模式:
-
DateTime类型默认走DateTimeConverter,需替换为自定义JsonConverter<datetime></datetime> - 推荐用
DateTime.ToString("yyyy-MM-dd HH:mm:ss")格式,注意空格不是T,且不带毫秒和时区后缀 - 若需保留时区信息(如
+08:00),用"o"或"s"格式反而更安全,强行去掉可能丢失上下文
var options = new JsonSerializerOptions
{
WriteIndented = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
options.Converters.Add(new DateTimeConverter("yyyy-MM-dd HH:mm:ss"));
// 注意:DateTimeConverter 是你自己写的继承 JsonConverter<datetime> 的类
</datetime>
Newtonsoft.Json 怎么配 DateFormatString?
老项目还在用 Newtonsoft.Json 的话,别用全局 JsonConvert.DefaultSettings(线程不安全),优先用实例化 JsonSerializerSettings:
-
DateFormatString只影响DateTime和DateTimeOffset,对string字段无效 - 设成
"yyyy-MM-dd HH:mm:ss"后,T就消失了,但要注意:如果原始值是DateTimeKind.Unspecified,反序列化时不会自动补时区,可能被当成本地时间处理 - 若 API 要同时支持前后端时区协商,建议显式用
DateTimeOffset替代DateTime,再配DateFormatHandling = DateFormatHandling.IsoDateFormat
var settings = new JsonSerializerSettings
{
DateFormatString = "yyyy-MM-dd HH:mm:ss",
NullValueHandling = NullValueHandling.Ignore
};
string json = JsonConvert.SerializeObject(data, settings);
全局配置 vs 局部配置:哪个更容易踩坑?
全局改(如 MvcJsonOptions 或 services.AddControllers().AddJsonOptions())看似一劳永逸,但风险高:
- 所有控制器、所有
DateTime字段全被套用同一格式,包括你本想保留 ISO 标准的审计日志字段 - Swagger 文档里显示的示例也会变,但 OpenAPI 规范默认期望 ISO 格式,可能误导前端开发者
- 如果项目混用
System.Text.Json和Newtonsoft.Json(比如 SignalR 用前者,旧 API 用后者),全局设置互相不生效,问题更隐蔽
真正稳妥的做法:按接口粒度控制——在特定 Action 返回时手动调用 JsonSerializer.Serialize(..., options),或给 DTO 类加 [JsonConverter] 特性,只改该字段。











