我有一个具有自定义JsonConverter
的类,如下所示:
[JsonConverter(typeof(TheShapeSerializer))]
public class TheShape : IShape {
//....
}
我无法更改课程。自定义序列化程序的工作方式不适合我的需求。
是否可以使用默认的序列化程序而不是TheShapeSerializer序列化TheShape的实例?
沿着同一行,是否有一种方法可以根据给定条件在序列化时间选择多个转换器?
答案 0 :(得分:3)
选择JsonConverters的顺序为documented,如下所示:
使用JsonConverter的优先级是成员属性,然后是class属性,最后是传递给JsonSerializer的所有转换器。
因此,您无法使用JsonConverterAttribute
禁用通过JsonSerializerSettings.Converters
应用的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
的类型中,则可以创建一个custom contract resolver来覆盖DefaultContractResolver.ResolveContractConverter
并为{{1}返回null
}。首先定义以下合同解析器:
TheShape
然后,出于here所述的性能原因,在以下位置定义静态成员:
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);
}
}
并序列化如下:
static IContractResolver shapeResolver = new ConverterDisablingContractResolver(new[] { typeof(TheShape) });
演示两个选项here的演示小提琴。
沿着同一行,是否有一种方法可以根据给定条件在序列化时间选择多个转换器?
显然,您可以根据某些运行时条件向var settings = new JsonSerializerSettings
{
ContractResolver = shapeResolver,
};
var json = JsonConvert.SerializeObject(root, settings);
添加不同的转换器。但是,如果您想将静态应用的转换器替换为运行时转换器,则需要适当地设置您的类型,例如通过使用this answer中的JsonSerializerSettings.Converters
到 Why Json.net does not use customized IsoDateTimeConverter? 。