【问题标题】:Ignore property with attribute in custom JSON converter在自定义 JSON 转换器中忽略具有属性的属性
【发布时间】:2020-08-19 00:22:20
【问题描述】:

我们正在使用.NET Core 3.1。我们有一个用于 DateTimeDateTime? 属性的自定义 JSON 转换器。

JsonDateTimeConverter.cs

public class JsonDateTimeConverter : DateTimeConverterBase
{
    public override bool CanConvert(Type objectType)
    {
        // I want to return false for object properties which have attribute "TimeZoneIgnore"
        
        return objectType == typeof(DateTime) || objectType == typeof(DateTime?);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // convert datetime to timezone
        DateTime? dateTime = (value as DateTime?).ConvertToTimeZone("CEST");

        writer.WriteValue(dateTime);
        writer.Flush();
    }
}

TimeZoneIgnore.cs

[AttributeUsage(AttributeTargets.Property)]
public class TimeZoneIgnore : Attribute { }

Bank.cs

public class Bank
{
    public string Name { get; set; }
    public DateTime ConvertThis { get; set; }
    [TimeZoneIgnore]
    public DateTime DontConvertThis { get; set; }
}

TestController.cs

[HttpGet]
public IActionResult Test123()
{
    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.Converters.Add(new JsonDateTimeConverter());
    
    return Json(new Bank()
    {
        Name = "Test bank",
        ConvertThis = new DateTime(2020, 8, 18, 15, 7, 1),
        DontConvertThis = new DateTime(2020, 8, 18, 15, 7, 1)
    }, settings);
}

对于具有TimeZoneIgnore 属性的对象属性,如何在CanConvert(Type objectType) 中返回false

【问题讨论】:

    标签: c# asp.net-core json.net


    【解决方案1】:

    JsonConverter 没有上下文来确定它被应用于哪个属性,因此没有一种简单的方法可以从其中获取属性。另一方面,ContractResolver 确实具有上下文信息,因为它负责将 JSON 属性映射到类属性。事实证明,您还可以使用ContractResolver 以编程方式应用或删除JsonConverters

    因此,您可以使用自定义ContractResolver 根据[TimeZoneIgnore] 属性的存在与否有条件地应用它,而不是在设置中全局应用您的JsonDateTimeConverter。这是解析器所需的代码:

    public class ConditionalDateTimeResolver : DefaultContractResolver
    {
        static readonly JsonConverter DateTimeConverter = new JsonDateTimeConverter();
    
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty prop = base.CreateProperty(member, memberSerialization);
            if (DateTimeConverter.CanConvert(prop.PropertyType) && 
                !prop.AttributeProvider.GetAttributes(typeof(TimeZoneIgnore), true).Any())
            {
                prop.Converter = DateTimeConverter;
            }
            return prop;
        }
    }
    

    要使用解析器,请将其添加到 JsonSerializerSettings 而不是添加转换器:

    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.ContractResolver = new ConditionalDateTimeResolver();
    // settings.Converters.Add(new JsonDateTimeConverter());          <-- remove this line
    

    这是一个工作演示:https://dotnetfiddle.net/8LBZ4S

    【讨论】:

    • 谢谢,这正是我需要的。
    • 没问题;很高兴我能帮上忙。
    猜你喜欢
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多