C#JsonConvert使用默认转换器而不是自定义转换器

isa*_*zan 6 c# json.net

我有一个具有自定义的类,如下所示JsonConverter

[JsonConverter(typeof(TheShapeSerializer))]
public class TheShape : IShape {
//....
}
Run Code Online (Sandbox Code Playgroud)

我不能改变班级。自定义序列化器的工作方式不适合我的需求。

有没有一种方法可以使用默认的序列化程序而不是TheShapeSerializer来序列化TheShape的实例?

同样,是否有一种方法可以让多个转换器根据给定条件在串行化时间选择?

dbc*_*dbc 5

选择JsonConverters的顺序记录如下:

使用JsonConverter的优先级是成员属性,然后是类属性,最后是传递给JsonSerializer的所有转换器。

因此,你不能禁用JsonConverter通过应用JsonConverterAttribute使用JsonSerializerSettings.Converters。相反,您有以下选择。

首先,如果您TheShape直接通过您控制的某种类型来引用您,则可以NoConverter从此答案中抓取到有选择地使用默认JSON转换器,然后使用JsonConverterAttribute或将其应用于引用成员JsonPropertyAttribute.ItemConverterType,例如,如下所示:

public class ShapeContainer
{
    [JsonConverter(typeof(NoConverter))]
    public TheShape Shape { get; set; }

    [JsonProperty(ItemConverterType = typeof(NoConverter))]
    public List<TheShape> Shapes { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在NoConverter将取代TheShapeSerializer应用它的属性,并导致Json.NET退回到默认序列化。

其次,如果,你不能成员属性添加到类型TheShape时,你可以创建一个自定义的合同解析器,它覆盖DefaultContractResolver.ResolveContractConverter和回报nullTheShape。首先定义以下合同解析器:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,定义一个静态成员某处如下,供描述的性能的原因在这里

static IContractResolver shapeResolver = new ConverterDisablingContractResolver(new[] { typeof(TheShape) });
Run Code Online (Sandbox Code Playgroud)

并序列化如下:

var settings = new JsonSerializerSettings
{
    ContractResolver = shapeResolver,
};
var json = JsonConvert.SerializeObject(root, settings);
Run Code Online (Sandbox Code Playgroud)

演示小提琴在这里显示了两种选择。

同样,是否有一种方法可以让多个转换器根据给定条件在串行化时间选择?

显然,您可以JsonSerializerSettings.Converters根据运行时条件向其中添加不同的转换器。但是,如果你想运行转换器,以取代静态应用转换器,则需要使用适当的设置你的类型,例如,OverridableJsonConverterDecorator这个回答不使用定制IsoDateTimeConverter为什么Json.net?