C# JsonConvert 使用默认转换器而不是自定义转换器 [英] C# JsonConvert using the default converter instead of the custom converter

查看:83
本文介绍了C# JsonConvert 使用默认转换器而不是自定义转换器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a class as follows that has a custom JsonConverter:

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

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

I cannot change the class. The way the custom serializer works is not appropriate for my needs.

有没有办法使用默认序列化器而不是 TheShapeSerializer 来序列化 TheShape 的实例?

Is there a way to serialize an instance of TheShape using the default serializer instead of TheShapeSerializer?

按照同样的思路,有没有一种方法可以在序列化时根据给定条件选择多个转换器?

Along the same lines, is there a way to have multiple converters that can be selected at serialization time based on a given condition?

推荐答案

选择JsonConverters的顺序是记录如下:

The order in which JsonConverters are selected is documented as follows:

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

The priority of which JsonConverter is used is member attribute, then class attribute, and finally any converters passed to the JsonSerializer.

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

Thus you cannot disable a JsonConverter applied via JsonConverterAttribute using JsonSerializerSettings.Converters. Instead, you have the following options.

首先,如果您的 TheShape 被您控制的某种类型直接引用,您可以从 这个答案 有选择地使用默认 JSON 转换器 并使用 JsonConverterAttributeJsonPropertyAttribute.ItemConverterType,例如如下:

Firstly, if your TheShape is being referred to directly by some type you control, you could grab NoConverter from this answer to Selectively use default JSON converter and apply it to the referring members using JsonConverterAttribute or JsonPropertyAttribute.ItemConverterType, e.g. as follows:

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 回退到默认序列化.

Now NoConverter will supersede TheShapeSerializer for the properties where it is applied, and cause Json.NET to fall back on default serialization.

其次,如果您无法将成员属性添加到使用 TheShape 的类型,您可以创建一个 自定义合约解析器,覆盖 DefaultContractResolver.ResolveContractConverter 并为 TheShape 返回 null.首先定义如下合约解析器:

Secondly, if you cannot add member attributes to types where TheShape is used, you could create a custom contract resolver that overrides DefaultContractResolver.ResolveContractConverter and returns null for TheShape. First define the following contract resolver:

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);
    }
}

然后,出于性能原因,如下定义某处的静态成员,此处:

Then, define a static member somewhere as follows, for performance reasons described here:

static IContractResolver shapeResolver = new ConverterDisablingContractResolver(new[] { typeof(TheShape) });

并序列化如下:

var settings = new JsonSerializerSettings
{
    ContractResolver = shapeResolver,
};
var json = JsonConvert.SerializeObject(root, settings);

演示小提琴显示两个选项这里.

Demo fiddle showing both options here.

同理,有没有一种方法可以在序列化时根据给定条件选择多个转换器?

显然,您可以根据某些运行时条件向 JsonSerializerSettings.Converters 添加不同的转换器.但是如果你想用运行时转换器取代静态应用的转换器,你需要适当地设置你的类型,例如通过使用 this answer 中的 OverridableJsonConverterDecorator为什么 Json.net 不使用自定义的 IsoDateTimeConverter?.

Obviously you could add different converters to JsonSerializerSettings.Converters depending on some runtime condition. But if you want to supersede statically applied converters with runtime converters, you would need to set up your types appropriately, e.g. by using OverridableJsonConverterDecorator from this answer to Why Json.net does not use customized IsoDateTimeConverter?.

这篇关于C# JsonConvert 使用默认转换器而不是自定义转换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆