最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

dotnet 10 新的 JsonIgnoreCondition

网站源码admin1浏览0评论

dotnet 10 新的 JsonIgnoreCondition

dotnet 10 新的 JsonIgnoreCondition

Intro

之前提了一个 api 建议为 JsonIgnore 添加两个扩展,WhenReadingWhenWriting,主要的一个用例是 WhenReading 我们的 Api Response 里有一个字段非常的大,不需要在 response 里包含,但是从 json 里反序列化时时需要地所以不能简单地直接忽略,在使用 Newtonsoft.Json 时使用 ShouldSerialize 约定方法在序列化的时候忽略,如果有一个 WhenWriting 的 ignore 选项可以比较方便地从 Newtonsoft.Json 做迁移,去年的时候 api review approved 了,之前看到有一个关联的 PR 不过后来一直没有更新,于是尝试自己提了一个 PR 以提供支持

New Api

代码语言:javascript代码运行次数:0运行复制
namespace System.Text.Json.Serialization;

public enum JsonIgnoreCondition
{
  Never,
  Always,
  WhenWritingDefault,
  WhenWritingNull,
+ WhenWriting,
+ WhenReading,
}

JsonIgnoreCondition 新增了 WhenWriting/WhenReading 选项,在序列化和反序列化时进行忽略

Sample

下面我们来看一个简单的使用示例:

代码语言:javascript代码运行次数:0运行复制
sealed classPerson
{
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)]
    publicint Id { get; set; }
    
    public required string Name { get; set; }

    
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)]
    publicstring? Description { get; set; }

    public override string ToString()
    {
        return$"{Id}-{Name}";
    }
}
代码语言:javascript代码运行次数:0运行复制
var p1 = new Person
{
    Id = 1,
    Name = "Jane",
    Description = "Jane J"
};

Console.WriteLine("Person1");
Console.WriteLine(p1.ToJson()); // ToJson() 是一个基于 Newtonsoft.Json 的扩展方法,来方便做一些测试
var jsonP1 = JsonSerializer.Serialize(p1);
Console.WriteLine(jsonP1);
var p1Deserialized = JsonSerializer.Deserialize<Person>(jsonP1);
Console.WriteLine(p1Deserialized.ToJson());

输出结果如下:

person sample output

可以看到 Id 因为添加了 WhenWritingJsonIgnoreCondition 的,在序列化的时候被忽略了,只有 Name 和 Description 输出了,在之后的反序列化中,因为 Description 添加了 [JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)] 所以 Description 是没有更新值的,值是 null 又因为默认忽略了 null 的输出,所以最后的输出结果中我们是没有看到 Description

相信这个例子可以比较好的理解其用法,在测试的过程中还发现了一个有趣的事情,下面也分享一下

接下来示例用到的 model 定义如下:

代码语言:javascript代码运行次数:0运行复制

sealed record User(int UserId, string UserName);

sealed record User2([property:JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)]int UserId, string UserName);

sealed record User3(
    [property:JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)]int UserId, 
    string UserName, 
    [property:JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)]string? Description
    );

sealed record User4
{
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)]
    publicint UserId { get; init; }

    public required string UserName { get; init; }

    [JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)]
    publicstring? Description { get; set; }
}

注意的话会发现这几个都是 record 测试示例如下:

代码语言:javascript代码运行次数:0运行复制
var user1 = new User(1, "Mike");
var user2 = new User2(1, "Mike");
var user3 = new User3(1, "Mike", "Michael");
var user4 = new User4 { UserId = 1, UserName = "Alice", Description = "Alice " };

Console.WriteLine("User1");
Console.WriteLine(user1.ToJson());
var json1 = JsonSerializer.Serialize(user1);
Console.WriteLine(json1);
var user1Deserialized = JsonSerializer.Deserialize<User>(json1);
Console.WriteLine(user1Deserialized);

Console.WriteLine("User2");
Console.WriteLine(user2.ToJson());
var json2 = JsonSerializer.Serialize(user2);
Console.WriteLine(json2);
var user2Deserialized = JsonSerializer.Deserialize<User2>(json2);
Console.WriteLine(user2Deserialized);

Console.WriteLine("User3");
Console.WriteLine(user3.ToJson());
var json3 = JsonSerializer.Serialize(user3);
Console.WriteLine(json3);
var user3Deserialized = JsonSerializer.Deserialize<User3>(json3);
Console.WriteLine(user3Deserialized);

Console.WriteLine("User4");
Console.WriteLine(user4.ToJson());
var json4 = JsonSerializer.Serialize(user4);
Console.WriteLine(json4);
var user4Deserialized = JsonSerializer.Deserialize<User4>(json4);
Console.WriteLine(user4Deserialized);

输出结果如下:

users sample output

  • User1 是没有使用 JsonIgnore attribute 的,序列化和反序列化属性都有输出和设置
  • User2 设置了 Id 使用 [property:JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)] UserId 在序列化的时候被忽略了
  • User3 设置了 Id 使用 [property:JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)] UserId 在序列化的时候被忽略了,Description 设置了 [property:JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)] 但是从输出结果可以看出来,Description 还是有值的,这一点感觉有点问题,我们设置了反序列化应该忽略,不过它是在构造器上的,不是通过属性 setter 设置的,是不是也是可以接受的呢?晚点在 GitHub 上建一个 issue 看看大佬们的想法
  • User4 为了避免前面构造器的问题,我们使用一个普通的 property 来测试,同样的为 UserId 设置 [property:JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)] 并为 Description 设置 [property:JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)] ,从输出结果可以看出此时我们的 Description 在反序列化的时候是被忽略的
  • 目前使用 Source Generator 时也有一些类似的问题,并且 Generator 处理 WhenWriting 时有点问题,后续会进行修复,大家感兴趣可以尝试一下哈

More

新的 JsonIgnoreCondition 可以比较方便地只处理属性的序列化和反序列化时忽略,大家有类似的需求的话也可以尝试下哈

References

  • .cs
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-04-24,如有侵权请联系 cloudcommunity@tencent 删除var测试序列化迁移console

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论