推荐优先使用 System.Text.Json.Deserialize(),.NET 5+ 默认启用、性能高;仅在需 camelCase 转换、循环引用等特殊功能时选用 Newtonsoft.Json,并注意二者行为差异。
直接用 System.Text.Json 的 JsonSerializer.Deserialize 是最推荐的方式,.NET 5+ 默认启用、性能高、无额外依赖;若需兼容旧项目或特殊功能(如 camelCase 自动转换、循环引用),才考虑 Newtonsoft.Json。
这是 .NET Core 3.0 起内置的高性能 JSON 库,无需安装 NuGet 包(除非 targeting .NET Framework)。
常见错误:传入 null 字符串、类型不匹配、JSON 字段名与 C# 属性名不一致导致字段为默认值。
public,或用 [JsonPropertyName("xxx")] 显式映射字段名userName),C# 属性是 PascalCase(UserName),需配置 JsonSerializerOptions.PropertyNameCaseInsensitive = true
List),而非 IEnumerable
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var user = JsonSerializer.Deserialize(jsonString, options); 老项目或需要 JsonIgnore、JsonConverter 等高级特性时仍会用到它。注意它和 System.Text.Json 的行为差异较大。
典型问题:日期格式解析失败、空字符串转 null 报错、自定义 converter 不生效。
JsonConvert.DeserializeObject(json) 是入口函数,不是静态类方法NullValueHandling.Ignore 或 DefaultValueHandling.Ignore 控制空值行为"date": "2025-01-01",而 C# 属性是 DateTime?,默认能解析;但若含时区("2025-01-01T00:00:00Z"),建议显式设 DateFormatHandling = DateFormatHandling.IsoDateFormat
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
DateParseHandling = DateParseHandling.DateTime
};
var data = JsonConvert.DeserializeObject(jsonString, settings); 当 JSON 结构不确定(比如 API 返回字段随版本变化),别硬套强类型,优先用 JsonDocument 或 JsonElement 解析。
容易踩的坑:用完没调 doc.Dispose() 导致内存泄漏;或误把 JsonElement.Clone() 当深拷贝(其实只是复制引用)。
JsonDocument.Parse(jsonString) 返回只读树结构,适合只读查询JsonObject(.NET 6+)或 JObject(Newtonsoft)element.TryGetProperty("xxx", out var value),避免 KeyNotFoundException
using var doc = JsonDocument.Parse(jsonString);
var root = doc.RootElement;
if (root.TryGetProperty("status", out var status))
{
Console.WriteLine(status.GetString());
}抛出异常是常态,关键是怎么看懂错误信息。两种库的异常提示风格完全不同。
System.Text.Json 错误通常带位置(如 LineNumber: 3, BytePositionInLine: 12),但不告诉你“期望什么类型”;Newtonsoft.Json 提示更口语化(如 Cannot convert string to int),但位置信息弱。
JsonDocument.Parse 尝试解析)System.Text.Json 不支持私有构造)NotSupportedException: Deserialization of reference types without parameterless constructor is not supported,说明类写了带参构造且没留无参构造复杂嵌套对象或自定义 converter 场
