Как я могу сказать Json.NET игнорировать свойства в стороннем объекте?

В документации 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?

Ответ 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);

Ответ 2

К счастью, Newtonsoft.Json имеет переопределение в методе JsonConvert.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, они могут не использовать "безопасный" тип, который вы изначально предоставили.