自定义 JSON 合同解析器忽略所有没有自定义注释的属性

Custom JSON contract resolver to ignore all properties without a custom annotation

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

因此,在序列化此 class 时,我想忽略没有我的自定义属性的所有属性,并像这样为 属性 指定序列化名称:

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;
    }
}

我不确定在哪里添加 如果没有属性则忽略 部分。

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

顺便说一句,我建议您将 MyCustomProperty class 重命名为 MyCustomPropertyAttribute,使 standard conventions for classes that derive from System.Attribute. (Don't worry, the [MyCustomProperty("name")] annotation need not change, as the Attribute part is optional in annotations.) You should also apply the [AttributeUsage] 属性与自定义属性 class 保持一致表明如何使用它。最后,我建议您将 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