c# - 通过自定义属性 (json.net) 从序列化中排除属性

标签 c# serialization json.net custom-attributes

我需要能够控制某个类的某些属性如何/是否被序列化。最简单的情况是 [ScriptIgnore]。但是,我只希望这些属性在我正在处理的这种特定序列化情况下得到尊重 - 如果应用程序下游的其他模块也想序列化这些对象,则这些属性都不应妨碍。

所以我的想法是在属性上使用自定义属性 MyAttribute,并使用知道查找该属性的 Hook 初始化 JsonSerializer 的特定实例。

乍一看,我没有看到 JSON.NET 中的任何可用 Hook 点会为当前属性提供 PropertyInfo 来执行此类检查 - 仅提供属性的值。我错过了什么吗?或者更好的方法来解决这个问题?

最佳答案

这是一个基于 the accepted answer 的通用可重用“忽略属性”解析器:

/// <summary>
/// Special JsonConvert resolver that allows you to ignore properties.  See https://stackoverflow.com/a/13588192/1037948
/// </summary>
public class IgnorableSerializerContractResolver : DefaultContractResolver {
    protected readonly Dictionary<Type, HashSet<string>> Ignores;

    public IgnorableSerializerContractResolver() {
        this.Ignores = new Dictionary<Type, HashSet<string>>();
    }

    /// <summary>
    /// Explicitly ignore the given property(s) for the given type
    /// </summary>
    /// <param name="type"></param>
    /// <param name="propertyName">one or more properties to ignore.  Leave empty to ignore the type entirely.</param>
    public void Ignore(Type type, params string[] propertyName) {
        // start bucket if DNE
        if (!this.Ignores.ContainsKey(type)) this.Ignores[type] = new HashSet<string>();

        foreach (var prop in propertyName) {
            this.Ignores[type].Add(prop);
        }
    }

    /// <summary>
    /// Is the given property for the given type ignored?
    /// </summary>
    /// <param name="type"></param>
    /// <param name="propertyName"></param>
    /// <returns></returns>
    public bool IsIgnored(Type type, string propertyName) {
        if (!this.Ignores.ContainsKey(type)) return false;

        // if no properties provided, ignore the type entirely
        if (this.Ignores[type].Count == 0) return true;

        return this.Ignores[type].Contains(propertyName);
    }

    /// <summary>
    /// The decision logic goes here
    /// </summary>
    /// <param name="member"></param>
    /// <param name="memberSerialization"></param>
    /// <returns></returns>
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        if (this.IsIgnored(property.DeclaringType, property.PropertyName)
        // need to check basetype as well for EF -- @per comment by user576838
        || this.IsIgnored(property.DeclaringType.BaseType, property.PropertyName)) {
            property.ShouldSerialize = instance => { return false; };
        }

        return property;
    }
}

和用法:

var jsonResolver = new IgnorableSerializerContractResolver();
// ignore single property
jsonResolver.Ignore(typeof(Company), "WebSites");
// ignore single datatype
jsonResolver.Ignore(typeof(System.Data.Objects.DataClasses.EntityObject));
var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = jsonResolver };

关于c# - 通过自定义属性 (json.net) 从序列化中排除属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13588022/

相关文章:

c# - 如何将异常序列化为 Json

c# - Microsoft 服务总线 REST 客户端 - 从队列读取的问题

python - Django REST框架: raise error when extra fields are present on POST

c# - 如何将文件保存在asp.net中的文件夹中-路径名错误

c# - 如何缓存数据库表以防止在 Asp.net C# mvc 中进行许多数据库查询

c# - 在 EF 中插入/更新实体?

c# - C# 中的 JSON 到 XML 转换

c# - 如何在 ASP.NET Web API 中为 Json.NET 设置自定义 JsonSerializerSettings?

c# - JsonConvert.DeserializeObject<>(字符串)返回 $id 属性的空值

c# - 用于比较的通用约束