簡體   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