自定义 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; }
}
我希望将 [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; }
}