C#控制台待办清单实现不同属性类型任务的序列化读写存储咨询
解决方案
实现思路
- 采用.NET 内置System.Text.Json的多态序列化能力,无需引入第三方库
- 通过抽象基类定义通用任务属性,派生两类具体任务对应主/子任务
- 利用
JsonDerivedType特性自动在序列化时注入类型标识,反序列化时自动识别对应类型 - 重写两类任务的
ToString方法实现不同的输出格式
完整修改后代码
using System; using System.Collections.Generic; using System.IO; using System.Text.Json; using System.Text.Json.Serialization; // 抽象任务基类,标注派生类对应的类型标识 [JsonDerivedType(typeof(MainTodoItem), typeDiscriminator: "Main")] [JsonDerivedType(typeof(SubTodoItem), typeDiscriminator: "Sub")] public abstract class TodoItem { public string Description { get; set; } public DateTime? DueOn { get; set; } } // 主任务类 public class MainTodoItem : TodoItem { public override string ToString() { var dueStr = DueOn.HasValue ? $" (截止到 {DueOn.Value:yyyy-MM-dd HH:mm})" : string.Empty; return $"{Description}{dueStr}"; } } // 子任务类 public class SubTodoItem : TodoItem { public override string ToString() { var dueStr = DueOn.HasValue ? $" (截止到 {DueOn.Value:yyyy-MM-dd HH:mm})" : string.Empty; // 输出自带缩进 return $"\t{Description}{dueStr}"; } } internal static class Program { static private readonly string _saveFileName = "todo.json"; static void Main() { // 保存示例数据 { List<TodoItem> items = new List<TodoItem> { new MainTodoItem { Description = "Feed the dog" }, new MainTodoItem { Description = "Buy groceries", DueOn = new DateTime(2021, 9, 30, 16, 0, 0) }, new SubTodoItem { Description = "Buy milk" }, new SubTodoItem { Description = "Buy eggs" } }; // 序列化配置无需额外修改 string json = JsonSerializer.Serialize(items, new JsonSerializerOptions() { WriteIndented = true }); File.WriteAllText(_saveFileName, json); } // 读取并输出 { string json = File.ReadAllText(_saveFileName); List<TodoItem> items = JsonSerializer.Deserialize<List<TodoItem>>(json); foreach (var todo in items) Console.WriteLine(todo); } } }
效果说明
- 序列化后的JSON会自动为每个任务添加
$type字段标识任务类型,反序列化时会自动转换为对应的主/子任务实例 - 控制台输出时子任务会自动带缩进,无需额外判断处理
- 本方案适用于.NET 5及以上版本
内容的提问来源于stack exchange,提问作者Rarowcun
相关产品推荐
相关产品推荐

