.NET Json 序列化库对比和推荐

结论

  • Newtonsoft Json 经过长时间验证,System.Text.Json 有微软官方维护,两者功能也比较齐全,在大多数情况下推荐使用。
  • 如果对性能有非常高的需求,Utf8Json 是最快的。
  • 更高的性能需要使用二进制格式了。

原生 System.Text.Json

  • System.Text.Json 集成在 .NET core 3.0,旧版本需要从 nuget 安装。
  • 作者也是原 Newtonsoft Json 的作者,为了高性能重写了新库。
  • 性能优于 Newtonsoft Json。
  • 基本不支持多态,这是一个明显的缺点。
  • 序列化和反序列化:
// 序列化
var jsonString = JsonSerializer.Serialize(weatherForecast);
File.WriteAllText(fileName, jsonString); // .NET 默认 UTF-8 without BOM
// 异步序列化
using FileStream createStream = File.Create(fileName);
await JsonSerializer.SerializeAsync(createStream, weatherForecast);
await createStream.DisposeAsync();
// 反序列化
var forecastDeserialized = JsonSerializer.Deserialize<Forecast>(forecastJson, options)!;
// 序列化对象
public class Forecast
    // public property 默认序列化
    public DateTime Date { get; set; }
    // 指定不序列化
    [JsonIgnore]
    public DateTime Date { get; set; }
    // 默认值不序列化,也可以用 JsonSerializerOptions 全局指定
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public DateTime Date { get; set; }
    // field 默认不序列化,可以指定序列化。也可以通过 JsonSerializerOptions 全局设置。
    [JsonInclude]
    public DateTime Date;
    // 改变序列化名称
    [JsonPropertyName("celsius")]
    public int TemperatureC { get; set;}
// 序列化选项
var options = new JsonSerializerOptions
    // 序列化成格式文本,方便人类阅读
    WriteIndented = true,
    // 序列化 field
    IncludeFields = true,
    // 只读 property 默认也会序列化,如果不想序列化
    IgnoreReadOnlyProperties = true,
    // 全局指定不序列化默认值
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
    // 默认不允许出现注释,否则报错。要允许的话
    NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString,
    // 全局指定使用 camelCase
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    // 避免转义非 ASCII 字符
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
// 建议常用配置
private static readonly JsonSerializerOptions _jsonSerializerOptions = new()
    WriteIndented = true,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
    IgnoreReadOnlyProperties = true,
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
  • 只读 DOM:
var doc = JsonDocument.Parse(File.ReadAllText(packageConfigPath));
if (doc.RootElement.TryGetProperty("scopedRegistries", out var scopedRegistries))
// 支持注释
var json = JsonDocument.Parse(jsonText, new JsonDocumentOptions {CommentHandling = JsonCommentHandling.Skip});
  • 可读写的 DOM:
var config = JsonNode.Parse(File.ReadAllText(packageConfigPath)) ?? new JsonObject();
if (config["scopedRegistries"] is not JsonArray scopedRegistries)
    scopedRegistries = new JsonArray();
    config["scopedRegistries"] = scopedRegistries;

Newtonsoft Json

// 序列化
var jsonString = JsonConvert.SerializeObject(account, Formatting.Indented);
// 反序列化
var account = JsonConvert.DeserializeObject<Account>(json);

对比 Newtonsoft Json 与 System.Text.Json

Newtonsoft Json System.Text.Json
默认选项基本符合大多数人需求 要按需设置全局选项
默认序列化 public field 默认不序列化 public field
默认忽略大小写 默认强制大小写
尽量避免转义 默认转义非 ASCII 字符
默认支持注释 默认不支持注释
默认支持最后一个逗号 默认不支持
支持的基础类型更广 某些类型需要自己实现
支持多态 基本不支持多态
不支持异步 支持异步
  • 总体而言:
    • Newtonsoft Json 简单方便、功能多、性能低。
    • System.Text.Json 使用复杂、功能少、性能高。
  • 如果没有多态需求,并且使用 .NET core 3.0 以上版本,那么 System.Text.Json 更合适,但需要设置部分选项。

Utf8Json

var p = new Person { Age = 99, Name = "foobar" };
// Object -> byte[] (UTF8)
byte[] result = JsonSerializer.Serialize(p);
// byte[] -> Object
var p2 = JsonSerializer.Deserialize<Person>(result);