我编写了一个Json.NET转换器,该转换器将所有设置的标志输出为数组。
enum SampleEnum
{
None = 0,
ValueA = 2,
ValueB = 4
}
SampleEnum flags = SampleEnum.ValueA | SampleEnum.ValueB;
// JSON: ["ValueA", "ValueB"]
现在,如果flags
为SampleEnum.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
}
我希望看到的输出:
{}
我该怎么做,以便该属性被忽略而不是为空?
PS:我已经了解了条件属性序列化,但是ShouldSerialize方法不适用于我的情况,我还没有弄清楚如何为我的情况使用IContractResolver。
答案 0 :(得分:2)
custom JsonConverter
不能阻止其值被序列化,因为引用该属性的属性名称将在调用转换器时被写出。在Json.NET的体系结构中,包含类型的责任是确定要序列化其属性的哪个。然后,值转换器决定如何对要写入的值进行序列化。
或者,即使应用了转换器,设置DefaultValueHandling.Ignore
也可以用于跳过enum
成员的序列化。由于SampleEnum.None
的值为0
,因此它是标志枚举的默认值。启用此设置(无论是否应用转换器)时,将跳过具有此值的成员。
您可以通过JsonPropertyAttribute.DefaultValueHandling
来应用DefaultValueHandling
:
public class SerializedClass
{
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
[JsonConverter(typeof(ArrayEnumConverter))]
public SampleEnum SampleEnum { get; set; }
}
提琴here。
偶然地,您应该考虑使用[Flags]
属性标记SampleEnum
:
[Flags]
public enum SampleEnum
{
None = 0,
ValueA = 2,
ValueB = 4
}
这是标志枚举的recommended best practice:
设计标志枚举
√确实将System.FlagsAttribute应用于标记枚举。不要将此属性应用于简单的枚举。