选择JsonConverters的顺序为documented如下:
使用JsonConverter的优先级是成员属性,然后是类属性,最后是传递给JsonSerializer的任何转换器。
因此,您不能使用JsonSerializerSettings.Converters 禁用通过JsonConverterAttribute 应用的JsonConverter。相反,您有以下选择。
首先,如果您的TheShape 被您控制的某种类型直接引用,您可以将NoConverter 从this answer 抓取到Selectively use default JSON converter 并将其应用于引用成员使用JsonConverterAttribute 或 JsonPropertyAttribute.ItemConverterType,例如如下:
public class ShapeContainer
{
[JsonConverter(typeof(NoConverter))]
public TheShape Shape { get; set; }
[JsonProperty(ItemConverterType = typeof(NoConverter))]
public List<TheShape> Shapes { get; set; }
}
现在 NoConverter 将取代 TheShapeSerializer 应用它的属性,并导致 Json.NET 回退到默认序列化。
其次,如果您无法将成员属性添加到使用 TheShape 的类型,您可以创建一个覆盖 DefaultContractResolver.ResolveContractConverter 的 custom contract resolver 并为 TheShape 返回 null。首先定义如下合约解析器:
public class ConverterDisablingContractResolver : DefaultContractResolver
{
readonly HashSet<Type> types;
public ConverterDisablingContractResolver(IEnumerable<Type> types)
{
if (types == null)
throw new ArgumentNullException();
this.types = new HashSet<Type>(types);
}
bool ContainsType(Type type)
{
return types.Contains(type);
}
protected override JsonConverter ResolveContractConverter(Type objectType)
{
// This could be enhanced to deal with inheritance. I.e. if TBase is in types and has a converter then
// its converter should not be used for TDerived -- but if TDerived has its own converter then it should still be
// used, so simply returning null for TDerived would be wrong.
if (types.Contains(objectType))
return null;
return base.ResolveContractConverter(objectType);
}
}
然后,在某处定义一个静态成员如下,出于性能原因描述here:
static IContractResolver shapeResolver = new ConverterDisablingContractResolver(new[] { typeof(TheShape) });
并序列化如下:
var settings = new JsonSerializerSettings
{
ContractResolver = shapeResolver,
};
var json = JsonConvert.SerializeObject(root, settings);
演示小提琴显示两个选项here。
同理,有没有一种方法可以在序列化时根据给定条件选择多个转换器?
显然,您可以根据某些运行时条件向JsonSerializerSettings.Converters 添加不同的转换器。但是如果你想用运行时转换器取代静态应用的转换器,你需要适当地设置你的类型,例如通过使用OverridableJsonConverterDecorator 从this answer 到Why Json.net does not use customized IsoDateTimeConverter?。