JsonSerializer.Deserialize要求类型与JSON字段严格对齐,否则因null值、大小写不匹配、非ISO日期、空白输入等触发JsonException;而JsonDocument适用于结构不确定场景,解析轻量、安全可控,但需手动处理路径和释放资源。

直接用 JsonSerializer.Deserialize<t></t> 最快最稳,但前提是类型定义和 JSON 字段严格对齐;结构不确定、字段可选或只想取一两个值时,JsonDocument 更安全、更轻量。
为什么 JsonSerializer.Deserialize<t></t> 会突然报错?
它不宽容——不是“尽力而为”,而是“全对才过”。常见崩点不是语法错误,而是类型契约没守好:
-
JsonException: The JSON value could not be converted to System.Int32:JSON 里是"age": null,C# 属性却是int Age { get; set; },必须改成int?或加[JsonPropertyName("age")] - 字段名大小写不一致(如 JSON 是
"userName",C# 类是public string Username { get; set; }):默认区分大小写,得显式设new JsonSerializerOptions { PropertyNameCaseInsensitive = true } - 日期字段是
"2023/10/05":System.Text.Json 只认 ISO 8601(如"2023-10-05T00:00:00"),否则直接抛异常,需自定义JsonConverter<datetime></datetime> - 传入
null或空白字符串:会报The input does not contain any JSON tokens,务必先用string.IsNullOrWhiteSpace()检查
什么时候该放弃强类型,改用 JsonDocument?
当你面对的不是“标准响应体”,而是第三方 API 返回的混合结构、日志片段、配置片段,或只关心其中一两个字段时,硬套 Deserialize<t></t> 反而容易因字段缺失、类型漂移、空值嵌套而崩溃。
-
JsonDocument.Parse(json)不分配 .NET 对象,只建只读树结构,内存开销小 - 适合一次解析、多次读取,比如反复查
"data.items[0].id"和"error.code" - 必须调用
.Dispose()(推荐用using块),否则可能内存泄漏 - 访问路径要逐层判断:
root.TryGetProperty("data", out var dataElem) && dataElem.TryGetProperty("items", out var items),直接GetProperty遇到缺失字段就炸
处理非标 JSON 文件(带注释、尾逗号)怎么办?
标准 JsonSerializer 默认拒绝行内注释(//)、块注释(/* */)和对象末尾逗号({"a":1,}),这类文件直接 Deserialize 必报 JsonException。
- 启用宽松解析:
new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true } - 这两个选项只影响反序列化(读),不影响序列化(写)
- 仍不支持单引号字符串(
'name': 'abc')或未引号属性名({name: 'abc'})——这些已超出 JSON RFC 8259 范畴,得换解析器或预清洗
真正容易被忽略的是:JsonDocument 的 RootElement 是只读的,不能修改;而 JsonSerializer.Deserialize<t></t> 的类型定义一旦和 JSON 字段有微小偏差(比如一个字段多了一个空格、少了一个问号),就会静默失败或抛出路径模糊的异常——排查时一定要看 JsonException 的 Path 和 LineNumber 字段,而不是只盯着消息文本。


















