自定义的Json.NET转换器不应该序列化一个属性。

3

我写了一个Json.NET转换器,将所有设置的标志输出为数组。

enum SampleEnum
{
    None = 0,
    ValueA = 2,
    ValueB = 4
}

SampleEnum flags = SampleEnum.ValueA | SampleEnum.ValueB;
// JSON: ["ValueA", "ValueB"]

如果flagsSampleEnum.None,则该属性不应被序列化。因此,我不会将任何内容写入JsonWriter。以下是转换器的WriteJson方法的代码。

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    if (value is SampleEnum enumValue)
    {
        IEnumerable<SampleEnum> setFlags = GetSetFlags<SampleEnum>(enumValue);              

        IEnumerable<string> flagNames = setFlags
            .Where(flag => flag != SampleEnum.None) // Filter out 'None'
            .Select(flag => flag.ToString());

        if (flagNames.Any())
        {
            JArray jArray = JArray.FromObject(flagNames, serializer);
            jArray.WriteTo(writer);
        }
        // Else omit this property
    }
}

然而,如果我的类中有一个类型为SampleEnum的属性,并且其值为SampleEnum.None,则该属性将被序列化,JSON值为null。

class SerializedClass
{
    [JsonConverter(typeof(ArrayEnumConverter))]
    public SampleEnum EnumValue { get; set; }
}

SerializedClass obj = new SerializedClass
{
    EnumValue = SampleEnum.None
};
string json = JsonConvert.SerializeObject(obj, new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore
});

输出结果如下:
{
  "EnumValue": null
}

The output I wish to see:

{}

如何避免属性为null而被省略?

附注:我已经了解了有关条件属性序列化的知识,但在我的情况下ShouldSerialize方法并不适用,而且我还没有弄清楚如何在我的情况下使用IContractResolver。

1个回答

4

一个自定义的 JsonConverter无法阻止其值被序列化,因为在转换器被调用时,已经写出了引用它的属性名称。在 Json.NET 的架构中,决定序列化哪些属性是包含类型的责任;然后值转换器决定如何序列化正在写入的值。

作为替代方案,可以使用设置{{link2:DefaultValueHandling.Ignore}}跳过即使应用了转换器也不需要序列化enum成员。由于SampleEnum.None的值为0,它是您的标志枚举的默认值。当启用该设置时,具有此值的成员将被跳过,无论是否应用转换器。

您可以通过使用JsonPropertyAttribute.DefaultValueHandling来启用DefaultValueHandling
public class SerializedClass
{
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    [JsonConverter(typeof(ArrayEnumConverter))]
    public SampleEnum SampleEnum { get; set; }
}

这是一个样例 这里

顺便提一下,你应该考虑使用[Flags]属性标记你的SampleEnum

[Flags]
public enum SampleEnum
{
    None = 0,
    ValueA = 2,
    ValueB = 4
}

这是有关标志枚举的推荐最佳实践

设计标志枚举

√ DO 将System.FlagsAttribute应用于标志枚举。不要将此属性应用于简单枚举。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接