【问题标题】:Json.Net attribute to ignore all propertiesJson.Net 属性忽略所有属性
【发布时间】:2018-12-11 04:00:43
【问题描述】:

是否有一个属性告诉 json.net 忽略一个类的所有属性但包括所有字段(不管访问修饰符)?

如果没有,有没有办法创建一个?

基本上,我想要一个装饰类的属性,它与将[JsonIgnore] 放在每个属性的前面具有相同的效果。

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    如果你用[JsonObject(MemberSerialization.Fields)] 标记你的班级,那将让你大部分时间到达那里。此属性告诉 Json.Net 您希望它序列化类中的所有字段,而不考虑访问修饰符,但不考虑属性。

    但是,如果您的类中有任何自动属性(即使用 { get; set; } 声明的那些),那么此属性将导致编译器生成的支持字段也被序列化,这可能是您不想要的。要抑制这些,您需要使用自定义IContractResolver。您可以通过从DefaultContractResolver 继承并覆盖CreateProperty 方法来创建一个。在该方法中,检查该类是否应用了[JsonObject(MemberSerialization.Fields)] 属性,如果是,则检查该成员是否是编译器生成的字段。如果是,则将其设置为忽略。

    class CustomResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty prop = base.CreateProperty(member, memberSerialization);
            JsonObjectAttribute attr = prop.DeclaringType.GetCustomAttribute<JsonObjectAttribute>();
            if (attr != null && attr.MemberSerialization == MemberSerialization.Fields && 
                member.GetCustomAttribute<CompilerGeneratedAttribute>() != null)
            {
                prop.Ignored = true;
            }
            return prop;
        }
    }
    

    要使用解析器,您需要通过JsonSerializerSettings 将其传递给SerializeObject 方法:

    var settings = new JsonSerializerSettings
    {
        ContractResolver = new CustomResolver(),
        Formatting = Formatting.Indented
    };
    string json = JsonConvert.SerializeObject(yourObject, settings);
    

    这是一个概念证明:https://dotnetfiddle.net/aNXWbn

    【讨论】:

    • [JsonObject(MemberSerialization.Fields)] 是我要找的
    【解决方案2】:

    您可以创建一个自定义 IContractResolver 并决定根据您创建的 custom attribute 进行序列化:

    public class IgnorePropertyResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            var property = base.CreateProperty(member, memberSerialization);
    
            //Todo: Check your custom attribute. You have MemberInfo here to navigate to your class and GetCustomAttributes<>
            //e.g: property.ShouldSerialize = member.DeclaringType.GetCustomAttribute<JsonIgnoreAllProperties>() == null;
            property.ShouldSerialize = false; 
            return property;
        }
    }
    

    然后你需要将它注册为默认,这取决于你的环境。或者你直接使用它,那么你甚至不需要一个属性:

    string json =
        JsonConvert.SerializeObject(
            product,
            Formatting.Indented,
            new JsonSerializerSettings
            {
                ContractResolver = new IgnorePropertyResolver()
            }
        );
    

    attribute is created,例如:

    public class JsonIgnoreAllPropertiesAttribute : Attribute
    {
    }
    

    并使用:

    [JsonIgnoreAllProperties]
    public class ClassToSerialize
    {
         public int Ignored { get;set; }
         public int Serialized;
    }
    

    【讨论】:

    • 这不是“自定义属性”我想装饰我的类,以便考虑 all 字段并忽略 all 属性,就像我在每个属性前面都有 [JsonIgnore]
    • 是的,这似乎不受支持。所以如果你想:你需要创建一个自定义的[JsonIgnoreAllProperties]@kofifus
    • 有什么建议吗?
    【解决方案3】:

    您可以将[JsonObject(MemberSerialization.OptIn)] 属性添加到您的班级,然后所有内容都将被忽略,除非您通过在成员上使用[JsonProperty] 属性明确选择加入。

    [JsonObject(MemberSerialization.OptIn)]
    public class Address
    {
        [JsonProperty]
        private string _field1 = "bob";
    
        public string Line1 { get; set; }
    
        public string Line2 { get; set; }
    
        public string Line3 { get; set; }
    }
    

    例如

    using System;
    using AutoFixture;
    using Newtonsoft.Json;
    
    public class Program
    {
        public static void Main()
        {
            var fixture = new Fixture();
            var address = fixture.Create<Address>(); // Create an address filled with junk
    
            var json = JsonConvert.SerializeObject(address);
    
            Console.WriteLine(json);
        }
    }
    

    将输出:

    {"_field1":"bob"}
    

    【讨论】:

    • 谢谢,我正在专门寻找一个属性,如果我以后添加/删除字段等,我可以将其应用到类中并忘记它
    • 但是.. 来自 Kevin 的答案中的代码会做到这一点,@kofifus。它被标记为选择加入。这与排除所有内容完全一样,但您说的其他内容除外。
    • 想象一下我有十个字段,我需要十个 [JsonProperty] 和你的解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 2012-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多