gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 14:40:34 25 4
gpt4 key购买 nike

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

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

我无法更改类(class)。自定义序列化程序的工作方式不适合我的需要。

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

同样,有没有办法让多个转换器可以在序列化时根据给定条件进行选择?

最佳答案

JsonConverters被选中的顺序是documented如下:

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

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

首先,如果您的 TheShape 被您控制的某种类型直接引用,您可以从 this answer 获取 NoConverter 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并为 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);

显示两个选项的演示 fiddle here .

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

显然,您可以根据某些运行时条件向 JsonSerializerSettings.Converters 添加不同的转换器。但是如果你想用运行时转换器取代静态应用的转换器,你需要适本地设置你的类型,例如通过使用来自 this answerOverridableJsonConverterDecorator Why Json.net does not use customized IsoDateTimeConverter? .

关于C# JsonConvert 使用默认转换器而不是自定义转换器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57086654/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com