【问题标题】:Conditionally applying JsonConverter有条件地应用 JsonConverter
【发布时间】:2020-04-15 04:55:27
【问题描述】:

我有一个数据结构,用于对 TFS 进行 api 更新调用,我们将 Value 属性设置为通用的,效果很好。我们想在我们的客户端代码中使用枚举作为某些类型的表示,但它们序列化为整数。所以有[JsonConvert(typeof(StringEnumConverter))] 选项,在泛型上这是一个问题,因为它试图将所有值序列化为字符串,针对属性的枚举类型。它看起来像这样:

public class WorkItemUpdateData<T> : WorkItemUpdate
{
    [JsonConverter(typeof(StringEnumConverter))]
    [JsonProperty("value")]
    public T Value { get; set; }
}

当属性 T 仅为枚举时,是否可以有条件地应用转换器?

【问题讨论】:

    标签: c# .net json serialization


    【解决方案1】:

    通过实现自定义转换器并将其指定为转换器:

    public class OnlyEnumStringConverter : StringEnumConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value != null && value.GetType().IsEnum)
            {
                base.WriteJson(writer, value, serializer);
            }
            else
            {
                serializer.Serialize(writer, value);
            }
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (objectType.IsEnum)
            {
                return base.ReadJson(reader, objectType, existingValue, serializer);
            }
            else
            {
                return serializer.Deserialize(reader, objectType);
            }
        }
    }
    

    指定它:

    public class WorkItemUpdateData<T> : WorkItemUpdate
    {
        [JsonConverter(typeof(OnlyEnumStringConverter))]
        [JsonProperty("value")]
        public T Value { get; set; }
    }
    

    【讨论】:

    • 如果您使用CanConvert(value.GetType())CanConvert(objectType),您也将能够处理可为空的枚举类型。
    • 谢谢,完美运行。现在只需要弄清楚如何对其进行单元测试。
    【解决方案2】:

    有一个 WorkItemUpdateData 和一个 WorkItemUpdateEnumData 可能更容易“sideclass”这个?然后,可以在创建对象时而不是在序列化对象时进行应用 JsonConverter 的条件逻辑。

    public class WorkItemUpdateData<T> : WorkItemUpdate
    {
        [JsonProperty("value")]
        public T Value { get; set; }
    }
    
    public class WorkItemUpdateEnumData<T> : WorkItemUpdate
    {
        [JsonConverter(typeof(StringEnumConverter))]
        [JsonProperty("value")]
        public T Value { get; set; }
    }
    

    您还可以在设置器中包含一些内容以确保正确使用它们,例如

    if (!typeof(T).IsEnum) throw ... 
    

    【讨论】:

    • 我认为您在错误的类中指定了 JsonConverter 属性。你能检查一下吗?
    • @OguzOzgul 本来可以做队友的,我不清楚每个位到底做了什么,而且我没有一个项目来测试它。我只是假设这一点会得到解决,并且 OP 会适应他们的需求:)
    • 感谢您的想法。唯一的问题是调用代码不必关心使用哪个子类。
    • 在这种情况下,我建议@OguzOzgul 的其他答案将是唯一的出路。您确实必须更改调用者以了解正确的转换器,或者更改转换器以了解数据。将它装饰在物业上,它会一直运行,而且没有办法解决这个问题,你需要弄清楚用那个拳头滚动的方式。
    猜你喜欢
    • 2021-08-25
    • 2015-09-04
    • 2017-11-19
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多