【问题标题】:Custom JSON contract resolver to ignore all properties without a custom annotation自定义 JSON 合同解析器忽略所有没有自定义注释的属性
【发布时间】:2020-08-07 10:25:13
【问题描述】:

我希望将 [JsonProperty("name")]![JsonIgnore] 组合到我自己的自定义解析器中,我只需要一些语法方面的帮助。

所以当序列化这个类时,我想忽略所有没有我的自定义属性的属性,并像这样指定属性的序列化名称:

public class MyClass
{
    [MyCustomProperty("name")]
    public string SomeName { get; set; }

    [MyCustomProperty("value")]
    public string SomeValue { get; set; }
    
    public string AnotherName {get; set; }
    
    public string AnotherValue {get; set; }
}

预期结果:

{
    "name": "Apple",
    "value": "Delicious"
}

这是我使用解析器所取得的进展:

public class MyCustomProperty : Attribute
{
    public string Property { get; set; }
    public MyCustomProperty(string property)
    {
        Property = property;
    }
}

public class CustomResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        Type itemType = property.PropertyType.GetGenericArguments().First();
        MyCustomProperty customProperty = itemType.GetCustomAttribute<MyCustomProperty>();
        property.PropertyName = MyCustomProperty.Property;
        return property;
    }
}

我不确定在哪里添加 ignore if no attribute 部分。

【问题讨论】:

    标签: c# json.net json-serialization


    【解决方案1】:

    JsonProperty 上有一个AttributeProvider,您可以使用它来查找该属性的自定义属性。我建议你使用它。所以基本上你会尝试获取属性,如果它存在,你就像你正在做的那样设置名称,否则你设置Ignored = true

    顺便说一句,我建议您将MyCustomProperty 类重命名为MyCustomPropertyAttribute,以与派生自System.Attribute 的类保持一致的standard conventions。 (不用担心,[MyCustomProperty("name")] 注释不需要更改,因为Attribute 部分在注释中是可选的。)您还应该将[AttributeUsage] 属性应用于您的自定义属性类,以指示如何使用它.最后,我建议您将Property 重命名为PropertyName,以明确它是一个名称(字符串)而不是属性本身(例如PropertyInfo)。

    所以代码看起来像这样:

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class MyCustomPropertyAttribute : Attribute
    {
        public string PropertyName { get; set; }
        public MyCustomPropertyAttribute(string propertyName)
        {
            PropertyName = propertyName;
        }
    }
    
    public class CustomResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);
            MyCustomPropertyAttribute customAttribute = (MyCustomPropertyAttribute)property.AttributeProvider.GetAttributes(typeof(MyCustomPropertyAttribute), true).FirstOrDefault();
            if (customAttribute != null)
            {
                property.PropertyName = customAttribute.PropertyName;
            }
            else
            {
                property.Ignored = true;
            }
            return property;
        }
    }
    

    工作演示:https://dotnetfiddle.net/thQc0f


    综上所述,您实际上并不需要自定义解析器来获得您想要的行为。您可以简单地将[JsonObject(MemberSerialization.OptIn)] 属性应用到MyClass,然后在您想要包含的那些属性上使用普通的[JsonProperty] 属性。任何未标记的属性都将被忽略。 (请参阅 Json.Net 文档中的 Serialization Attributes。)

    [JsonObject(MemberSerialization.OptIn)]
    public class MyClass
    {
        [JsonProperty("name")]
        public string SomeName { get; set; }
    
        [MyCustomProperty("value")]
        public string SomeValue { get; set; }
        
        public string AnotherName {get; set; }
        
        public string AnotherValue {get; set; }
    }
    

    演示:https://dotnetfiddle.net/qY6nGR

    【讨论】:

    • 可以向解析器添加逻辑,使其仅针对一个或多个特定类执行其特殊行为。这可以通过多种方式完成——您可以在解析器中对类名进行硬编码;您可以在构造函数中传递类名,或者您可以引入另一个属性,该属性将应用于目标类以标记它们。在任何情况下,您都将在CreateProperty 中添加检查属性的DeclaringType 的名称是否与目标类名称匹配。这是使用构造方法的示例:dotnetfiddle.net/XSJnzC
    猜你喜欢
    • 2012-01-30
    • 1970-01-01
    • 2017-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多