创建预定义的JsonConvert属性

本文关键字:属性 JsonConvert 预定义 创建 | 更新日期: 2023-09-27 18:25:10

我的问题很简单。。我想做的是:

[JsonConverter(typeof(MyConverter)]
object SomeProperty {get;set;}

但是可以将其写为自定义属性,这样我就可以用预定义的JsonConverter属性来装饰我的属性。。例如

[MyCustomConverter]
object SomeProperty {get;set;}

在这种情况下会被视为[JsonConverter(typeof(MyConverter))]

有什么想法吗?

Br,Inx

创建预定义的JsonConvert属性

这不是一件小事,但如果您实现了一个将属性考虑在内的自定义IContractResolver,则可以做到这一点。

这需要几个步骤:

  1. 为属性创建一个扩展System.Attribute:的abstract基类

    public abstract class ConverterAttribute : Attribute
    {
        public abstract JsonConverter Converter { get; }
    }
    
  2. 接下来,您需要创建IContractResolver,它将实际使用您的属性1:

    public class CustomAttributeContractResolver : DefaultContractResolver
    {   
        protected override JsonObjectContract CreateObjectContract(Type objectType)
        {
            JsonObjectContract contract =
                base.CreateObjectContract(objectType);
            IEnumerable<JsonProperty> withoutConverter =
                contract.Properties.Where(
                    pr => pr.MemberConverter == null && 
                    pr.Converter == null);
            // Go over the results of calling the default implementation.
            // check properties without converters for your custom attribute
            // and pull the custom converter out of that attribute.
            foreach (JsonProperty property in withoutConverter)
            {
                PropertyInfo info = 
                    objectType.GetProperty(property.UnderlyingName);
                var converterAttribute =
                    info.GetCustomAttribute<ConverterAttribute>();
                if (converterAttribute != null)
                {
                    property.Converter = converterAttribute.Converter;
                    property.MemberConverter = converterAttribute.Converter;
                }
            }
            return contract;
        }
    }
    
  3. 创建覆盖ConverterAttribute.Converter的属性,返回您的自定义转换器:

    public class MyCustomConverterAttribute : ConverterAttribute
    {
        get { return new MyCustomConverter(); }
    }
    
  4. 用属性装饰你的班级:

    public class MyClass
    {
        [MyCustomConverter]
        public object MyProperty { get; set; }
    }
    
  5. 序列化或反序列化时,请在您使用的JsonSerializerSettings中指定约定冲突解决程序:

    var settings = new JsonSerializerSettings();
    settings.ContractResolver = new CustomAttributeContractResolver();
    string serialized = JsonConverter.SerializeObject(new MyClass());
    

我想说,这可能不值得这个小小的好处——你真正做的只是保存几个字符,除非你的属性做了其他事情。


1:我不确定MemberConverterConverter之间有什么区别。当序列化时,只需要Converter属性,但反序列化需要MemberConverter。我会继续挖掘,但希望有人能提供一些见解。看起来其他人也有同样的问题。

这似乎是不可能的。JsonConverterAttributeTypeConverterAttribute类都是密封的,它们是Json.NET用来提供自定义类型转换器的类。