忽略一些序列化的默认值
Ignoring some default values for serialization
tl;博士;在 Newtonsoft JSON.NET 中,如何忽略某些类型(枚举)而不是其他类型(整数)的默认值?
我的团队正在使用一个将协议缓冲区用于其业务实体的库。此 library/protobuf 中的每个枚举都有一个默认值 0,"ValueNotSet"。我的团队正在使用 Newtonsoft JSON.NET 来序列化这些实体。这是面包店库存的稀释示例:
public enum Flavor { ValueNotSet, Cherry, Blueberry, Cheese };
public class DanishInventory { public int QtyInStock; public Flavor; }
为了节约资源,我们不想序列化ValueNotSet
(现实世界的场景有很多枚举),但是零库存的丹麦奶酪是有效的,我们做 想要序列化为零。因此,我们不能在设置中使用 DefaultValueHandling = Ignore。
我创建了一个自定义 JsonConverter,但在调用 WriteJson(...) 时,密钥已经在 JsonWriter 中。因此,如果我什么都不写,JSON 是无效的,而且我没有看到一种明显的方法来回溯作者以覆盖密钥。那么忽略某些类型(例如枚举)而不是其他类型(例如整数)的默认值的最佳方法是什么?
请注意,枚举位于 NuGet 包中,无法修改,例如通过添加属性。
您可以使用 to 的 DefaultValueContractResolver
变体来排除所有具有默认值的枚举值属性:
public class EnumDefaultValueContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.DefaultValueHandling == null)
{
if (property.PropertyType.IsEnum)
{
//For safety you could check here if the default value is named ValueNotSet and only set IgnoreAndPopulate in that case.
//var defaultValue = Enum.ToObject(property.PropertyType, 0);
//if (defaultValue.ToString() == "ValueNotSet")
//{
property.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate; // Or DefaultValueHandling.Ignore if you prefer
//}
}
}
return property;
}
}
然后使用如下:
var resolver = new EnumDefaultValueContractResolver();
var settings = new JsonSerializerSettings { ContractResolver = resolver };
var json = JsonConvert.SerializeObject(inventory, settings);
您可能想要 cache the contract resolver for best performance。
演示 fiddle here.
许多序列化器(我相信包括 Json.NET)支持 ShouldSerialize*()
模式;如果您不介意在每次使用的基础上这样做,您可以这样做:
public class DanishInventory {
public int QtyInStock;
public Flavor;
public bool ShouldSerializeFlavor() => Flavor != 0;
}
tl;博士;在 Newtonsoft JSON.NET 中,如何忽略某些类型(枚举)而不是其他类型(整数)的默认值?
我的团队正在使用一个将协议缓冲区用于其业务实体的库。此 library/protobuf 中的每个枚举都有一个默认值 0,"ValueNotSet"。我的团队正在使用 Newtonsoft JSON.NET 来序列化这些实体。这是面包店库存的稀释示例:
public enum Flavor { ValueNotSet, Cherry, Blueberry, Cheese };
public class DanishInventory { public int QtyInStock; public Flavor; }
为了节约资源,我们不想序列化ValueNotSet
(现实世界的场景有很多枚举),但是零库存的丹麦奶酪是有效的,我们做 想要序列化为零。因此,我们不能在设置中使用 DefaultValueHandling = Ignore。
我创建了一个自定义 JsonConverter,但在调用 WriteJson(...) 时,密钥已经在 JsonWriter 中。因此,如果我什么都不写,JSON 是无效的,而且我没有看到一种明显的方法来回溯作者以覆盖密钥。那么忽略某些类型(例如枚举)而不是其他类型(例如整数)的默认值的最佳方法是什么?
请注意,枚举位于 NuGet 包中,无法修改,例如通过添加属性。
您可以使用 DefaultValueContractResolver
变体来排除所有具有默认值的枚举值属性:
public class EnumDefaultValueContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.DefaultValueHandling == null)
{
if (property.PropertyType.IsEnum)
{
//For safety you could check here if the default value is named ValueNotSet and only set IgnoreAndPopulate in that case.
//var defaultValue = Enum.ToObject(property.PropertyType, 0);
//if (defaultValue.ToString() == "ValueNotSet")
//{
property.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate; // Or DefaultValueHandling.Ignore if you prefer
//}
}
}
return property;
}
}
然后使用如下:
var resolver = new EnumDefaultValueContractResolver();
var settings = new JsonSerializerSettings { ContractResolver = resolver };
var json = JsonConvert.SerializeObject(inventory, settings);
您可能想要 cache the contract resolver for best performance。
演示 fiddle here.
许多序列化器(我相信包括 Json.NET)支持 ShouldSerialize*()
模式;如果您不介意在每次使用的基础上这样做,您可以这样做:
public class DanishInventory {
public int QtyInStock;
public Flavor;
public bool ShouldSerializeFlavor() => Flavor != 0;
}