C#中序列化含DateOnly与TimeOnly的对象至JSON文件失败问题
解决Newtonsoft.Json序列化DateOnly/TimeOnly类型的问题
Newtonsoft.Json默认不支持.NET 6+引入的DateOnly和TimeOnly类型,需要自定义JSON转换器来处理这两个类型的序列化与反序列化逻辑。以下是具体解决方案:
1. 自定义JSON转换器
创建两个转换器类,分别处理DateOnly和TimeOnly的格式转换:
// DateOnly转换器 public class DateOnlyConverter : JsonConverter<DateOnly> { private const string DefaultDateFormat = "yyyy-MM-dd"; public override DateOnly ReadJson(JsonReader reader, Type objectType, DateOnly existingValue, bool hasExistingValue, JsonSerializer serializer) { return DateOnly.ParseExact(reader.Value.ToString(), DefaultDateFormat, CultureInfo.InvariantCulture); } public override void WriteJson(JsonWriter writer, DateOnly value, JsonSerializer serializer) { writer.WriteValue(value.ToString(DefaultDateFormat, CultureInfo.InvariantCulture)); } } // TimeOnly转换器 public class TimeOnlyConverter : JsonConverter<TimeOnly> { private const string DefaultTimeFormat = "HH:mm:ss"; public override TimeOnly ReadJson(JsonReader reader, Type objectType, TimeOnly existingValue, bool hasExistingValue, JsonSerializer serializer) { return TimeOnly.ParseExact(reader.Value.ToString(), DefaultTimeFormat, CultureInfo.InvariantCulture); } public override void WriteJson(JsonWriter writer, TimeOnly value, JsonSerializer serializer) { writer.WriteValue(value.ToString(DefaultTimeFormat, CultureInfo.InvariantCulture)); } }
2. 应用转换器
有两种方式可以让Newtonsoft.Json使用这些转换器:
方式一:在类属性上标记特性
直接在information类的对应字段上添加[JsonConverter]特性:
public class information { [JsonProperty] [JsonConverter(typeof(DateOnlyConverter))] public DateOnly date; [JsonProperty] public string summary; [JsonProperty] [JsonConverter(typeof(TimeOnlyConverter))] public TimeOnly endTime; [JsonProperty] [JsonConverter(typeof(TimeOnlyConverter))] public TimeOnly startTime; }
方式二:全局配置转换器
如果项目中有多处使用DateOnly/TimeOnly序列化,建议全局配置转换器,避免重复标记:
var jsonSettings = new JsonSerializerSettings(); jsonSettings.Converters.Add(new DateOnlyConverter()); jsonSettings.Converters.Add(new TimeOnlyConverter());
3. 修正序列化代码
同时优化文件写入逻辑,避免流操作的潜在问题(如文件不存在时的异常、覆盖不完整等):
private static void WriteFile(DateOnly date, string summary, TimeOnly startTime, TimeOnly endTime) { var newAppointment = new information() { date = date, summary = summary, startTime = startTime, endTime = endTime }; var appointmentList = GetJsonInfo(); appointmentList.Add(newAppointment); // 使用全局配置序列化 var jsonSettings = new JsonSerializerSettings(); jsonSettings.Converters.Add(new DateOnlyConverter()); jsonSettings.Converters.Add(new TimeOnlyConverter()); string jsonContent = JsonConvert.SerializeObject(appointmentList, Formatting.Indented, jsonSettings); // 用File.WriteAllText简化文件操作 string fullPath = Path.Combine(_appointmentPath, "appointment.json"); File.WriteAllText(fullPath, jsonContent, Encoding.UTF8); } // 补充GetJsonInfo方法的反序列化逻辑(需同步使用转换器) private static List<information> GetJsonInfo() { string fullPath = Path.Combine(_appointmentPath, "appointment.json"); if (!File.Exists(fullPath)) { return new List<information>(); } string jsonContent = File.ReadAllText(fullPath); var jsonSettings = new JsonSerializerSettings(); jsonSettings.Converters.Add(new DateOnlyConverter()); jsonSettings.Converters.Add(new TimeOnlyConverter()); return JsonConvert.DeserializeObject<List<information>>(jsonContent, jsonSettings) ?? new List<information>(); }
关键说明
- 序列化和反序列化必须使用相同的转换器配置,否则会出现格式不匹配的错误
- 可以根据需求修改转换器中的日期/时间格式字符串(如
yyyy/MM/dd或HH:mm)
内容的提问来源于stack exchange,提问作者SoldatXwing
相关产品推荐
相关产品推荐

