System.Text.Json 是 .NET 6+ 读写 JSON 的首选方案,需注意大小写敏感、编码、路径、空值、日期枚举等细节,并推荐复用 static readonly JsonSerializerOptions。

直接用 System.Text.Json 读写 JSON 文件是当前 .NET 6+ 项目中最稳、最轻、最不需要额外依赖的方案。别碰 Newtonsoft.Json 除非你被旧代码或特定格式(比如 \/Date(...)\/)卡住。
用 JsonSerializer.Deserialize<T> 读配置前先确认类型和字段名是否对得上
常见错误不是“读不了”,而是抛 JsonException: The JSON value could not be converted to XXX。这基本等于告诉你:JSON 里有个字段叫 "userName",但你的 C# 类写的是 public string Username { get; set; },默认大小写敏感,直接不认。
- 要么加
[JsonPropertyName("userName")]显式绑定字段名 - 要么全局开启
PropertyNameCaseInsensitive = true(只对反序列化生效) - 别用
dynamic或object接收再转型——编译期检查没了,错误全堆到运行时 - 如果 JSON 字段可能缺失,对应属性声明为可空类型,比如
public int? Age { get; set; }
写入时用 File.WriteAllText + Encoding.UTF8 是底线操作
漏掉 Encoding.UTF8 参数,Windows 下默认用 ANSI 编码,中文立刻变乱码;手动拼接字符串再写入(比如 obj.ToString() + json),会破坏转义逻辑,生成非法 JSON。
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 正确写法:
File.WriteAllText("config.json", JsonSerializer.Serialize(config, options), Encoding.UTF8) - 路径不存在?
Directory.CreateDirectory(Path.GetDirectoryName("config.json"))得自己加,File.WriteAllText不会帮你建目录 - 想让文件人眼可读?开
WriteIndented = true,但别在高频日志写入场景用——缩进增加字符串长度和序列化开销 - 写入
null对象时,默认输出字符串"null",不是{}。业务上需要空对象占位,得提前判空:json = obj == null ? "{}" : JsonSerializer.Serialize(obj, options)
处理日期、枚举、Type 等特殊类型时别硬扛默认行为
DateTime 字段反序列化失败,90% 是因为 JSON 里给的是 "2024-05-12"(只有日期)或 "2024/05/12"(斜杠分隔),而 System.Text.Json 默认只认完整 ISO 8601 格式(带时间+时区)。枚举写成字符串要加转换器,Type 类型根本不能序列化。
- 日期字段不稳定?优先把属性类型改成
string,自己用DateTime.TryParse解析,留出容错空间 - 必须用
DateTime?写个自定义JsonConverter<DateTime>,在Read方法里试多种TryParseExact模板 - 枚举转字符串?加
options.Converters.Add(new JsonStringEnumConverter()),但它对DateTime完全无效 - 类里有
public Type EntityType { get; set; }?删掉,或改用string TypeName = typeof(MyClass).FullName存
大配置文件或只取部分字段时,别全量反序列化
几 MB 的 JSON 配置文件,用 JsonSerializer.Deserialize<Config>() 会一次性加载整个对象树到内存,容易 OOM;如果只是想读 "features.enabled" 这一个布尔值,全量解析纯属浪费。
- 只读部分字段 → 用
JsonDocument.Parse(File.ReadAllText(path)),它比JObject更省内存,支持快速导航和只读提取 - 流式读取超大文件 → 用
Utf8JsonReader手动推进,跳过无关字段,适合日志归档类场景 - 配置文件被其他进程占用?先写临时文件(如
config.json.tmp),再用File.Replace原子替换,避免中间态损坏
最常被忽略的一点:所有 JsonSerializerOptions 实例,只要不改写内部状态,就该声明为 static readonly。每次 new 一个不仅浪费 GC 压力,还可能因并发修改导致不可预期行为。

















