繁体   English   中英

使用 JSON.net 序列化时忽略接口中定义的属性

[英]Ignore property defined in interface when serializing using JSON.net

我有一个带有这样属性的接口:

public interface IFoo {
    // ...

    [JsonIgnore]
    string SecretProperty { get; }

    // ...
}

我希望在序列化所有实现类时忽略SecretProperty 但似乎我必须在该属性的每个实现上定义JsonIgnore属性。 有没有办法在JsonIgnore为每个实现添加JsonIgnore属性的情况下实现这一点? 我没有找到任何对我有帮助的序列化程序设置。

经过一番搜索,我发现了这个问题:

使用 JSON.NET 序列化时如何将属性从接口继承到对象

我拿了 Jeff JsonIgnoreAttribute的代码并添加了JsonIgnoreAttribute检测,所以它看起来像这样:

class InterfaceContractResolver : DefaultContractResolver
{
    public InterfaceContractResolver() : this(false) { }

    public InterfaceContractResolver(bool shareCache) : base(shareCache) { }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        var interfaces = member.DeclaringType.GetInterfaces();
        foreach (var @interface in interfaces)
        {
            foreach (var interfaceProperty in @interface.GetProperties())
            {
                // This is weak: among other things, an implementation 
                // may be deliberately hiding an interface member
                if (interfaceProperty.Name == member.Name && interfaceProperty.MemberType == member.MemberType)
                {
                    if (interfaceProperty.GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Any())
                    {
                        property.Ignored = true;
                        return property;
                    }

                    if (interfaceProperty.GetCustomAttributes(typeof(JsonPropertyAttribute), true).Any())
                    {
                        property.Ignored = false;
                        return property;
                    }
                }
            }
        }

        return property;
    }
}

在我的JsonSerializerSettings使用这个InterfaceContractResolver ,所有在任何接口中具有JsonIgnoreAttribute属性JsonIgnoreAttribute被忽略,即使它们具有JsonPropertyAttribute (由于内部if块的顺序)。

在最新版本的 Json.NET 中,将[JsonIgnore]应用于接口属性现在可以正常工作并成功地防止它们被所有实现类型序列化,只要在声明接口的同一类上声明属性即可。 不再需要自定义合同解析器。

例如,如果我们定义以下类型:

public interface IFoo 
{
    [JsonIgnore]
    string SecretProperty  { get; set; }

    string Include { get; set; }
}

public class Foo : IFoo 
{
    public string SecretProperty  { get; set; }
    public string Include { get; set; }
}

然后以下测试在 Json.NET 11 和 12(可能还有更早的版本)中通过:

var root = new Foo
{
    SecretProperty  = "Ignore Me",
    Include = "Include Me",
};

var json = JsonConvert.SerializeObject(root);

Assert.IsTrue(json == "{\"Include\":\"Include Me\"}");// Passes

演示在这里这里摆弄。

我相信这是在 Json.NET 4.0.3中添加的,尽管发行说明中没有明确提到JsonIgnore

新功能 - JsonObject 和 JsonProperty 属性现在可以放置在接口上,并在序列化实现对象时使用。

(实现可以在JsonTypeReflector.GetAttribute<T>(MemberInfo memberInfo) 。)

但是,正如Vitaly指出的,当属性是从声明接口的类的基类继承时,这不起作用。 演示小提琴在这里

我发现创建一个只包含我想要的属性的 DTO 并将该对象序列化为 JSON 是最简单的。 它创建了许多小的、特定于上下文的对象,但管理代码库要容易得多,我不必考虑我正在序列化的内容与我忽略的内容。

您应该在类名前添加[DataContract]

它将默认值从包含所有属性更改为仅包含显式标记的属性。 之后,在要包含在 JSON 输出中的每个属性前添加“[DataMember]”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM