【问题标题】:How can I tell Json.NET to ignore properties in a 3rd-party object?如何告诉 Json.NET 忽略第 3 方对象中的属性?
【发布时间】:2014-09-09 16:18:05
【问题描述】:

Json.NET 文档说您使用 JsonIgnore 不序列化您的类中的某些属性:

public class Account
{
    public string FullName { get; set; }
    public string EmailAddress { get; set; }

    [JsonIgnore]
    public string PasswordHash { get; set; }
}

如何让 Json.NET 在使用 JsonConvert.SerializeObject 序列化第 3 方对象时忽略特定属性?

【问题讨论】:

  • @GuillaumeCR:您删除的答案是一个好的开始——只需添加一个代码示例,这将是一个好的答案
  • @AndrewWhitaker 我会等我一分钟,但现在工作电话;)

标签: c# json json.net


【解决方案1】:

制作自定义合约解析器:

public class ShouldSerializeContractResolver : DefaultContractResolver
{
    public static ShouldSerializeContractResolver Instance { get; } = new ShouldSerializeContractResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);        
        if (typeof(Account).IsAssignableFrom(member.DeclaringType) && member.Name == nameof(Account.PasswordHash))
        {
            property.Ignored = true;
        }
        return property;
    }
}

我如何测试它:

        var account = new Account
        {
            PasswordHash = "XXAABB"
        };
        var settings = new JsonSerializerSettings
        {
            ContractResolver = ShouldSerializeContractResolver.Instance
        };
        var json = JsonConvert.SerializeObject(account, settings);
        Console.WriteLine(json);

【讨论】:

  • 小优化:if (!property.Ignored && property.DeclaringType == typeof(Account) && property.PropertyName == "PasswordHash")
  • 这是微不足道的,而且可以说更慢,因为 IContractResolver 在所有类之间共享并且大多数属性都不会被忽略,所以大多数时候我们浪费时间检查!property.Ignored。每个类也懒惰地创建一次合同,所以我认为最好保持简单。
  • 这是否也根据序列化实例的值有条件地工作?我在任何地方都找不到会员的价值。
  • 没关系,我已经找到了。不要设置property.Ignore,而是设置property.ShouldSerialize。这可以处理每个值。
【解决方案2】:

幸运的是,Newtonsoft.JsonJsonConvert.SerializeObject() 方法有一个覆盖,它允许我们提供一个类型,因此生成的 JSON 不包含该类型中不存在的属性。因此,要消除属性,您可以制作 Account 类的安全副本,删除所有敏感属性,并为其命名:

public class AccountJSON
{
    public string FullName { get; set; }
    public string EmailAddress { get; set; }
}

序列化时提供其类型:

var TheAccount = DBContext.Accounts.Find(1);
var TheJSON = Newtonsoft.Json.JsonConvert.SerializeObject(TheAccount, typeof(AccountJSON));

注意:当序列化程序遍历对象时,这可能仅适用于第一级深度。如果 Account 对象具有引用更多 Account 对象的延迟加载属性,则它们可能不会使用您最初提供的“安全”类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 2017-11-12
    • 2017-01-14
    • 2011-12-17
    相关资源
    最近更新 更多