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

时间:2018-11-20 20:42:15

标签: c# json.net

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

[JsonConverter(typeof(TheShapeSerializer))]
public class TheShape : IShape {
//....
}

我无法更改课程。自定义序列化程序的工作方式不适合我的需求。

是否可以使用默认的序列化程序而不是TheShapeSerializer序列化TheShape的实例?

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

1 个答案:

答案 0 :(得分:3)

选择JsonConverters的顺序为documented,如下所示:

  

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

因此,您无法使用JsonConverterAttribute禁用通过JsonSerializerSettings.Converters应用的JsonConverter。相反,您有以下选择。

首先,如果您控制的某种类型直接引用了您的TheShape,则可以将NoConverterthis answer抓到 Selectively use default JSON converter 并使用JsonConverterAttributeJsonPropertyAttribute.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?