我正在try 从Newtonsoft.Json迁移到System.Text.Json,并且我正在try 找到一种方法来判断是否我的所有数据都已被"捕获"并且被正确映射(Re:PolyphismOptions),因为我已经使用了大量的泛型/抽象/接口类型.

有没有办法做到这一点:

  1. 确定它目前try 转换的类型?JsonTypeInfoResolver中的GetTypeInfo()似乎只返回它找到的"基本"类型.

  2. 抛出某种异常或错误,IFF它发现一个问题?

提前谢谢您!

推荐答案

在构造已声明类型的约定时,我不知道有什么方法可以使实际类型被序列化.

但是,您可以强制System.Text.Json在序列化意外派生类型时自动引发异常.为此,您需要创建一个JsonTypeInfo modifier,以自动将所有相关非密封类型的JsonPolymorphismOptions.UnknownDerivedTypeHandling设置为FailSerialization:

public static partial class JsonExtensions
{
    public static Action<JsonTypeInfo> SetupUnknownDerivedTypeHandling(bool objectsOnly = false) =>
        (typeInfo) =>
    {
        // Polymorphism using type discriminators is only supported for type hierarchies that use the default converters for objects, collections, and dictionary types.
        if (typeInfo.Kind == JsonTypeInfoKind.None || typeInfo.Type.IsSealed || typeInfo.Type == typeof(object))
            return;
        if (objectsOnly && typeInfo.Kind != JsonTypeInfoKind.Object)
            return;
        // TODO: decide whether to fail serialization even for types marked with
        // [JsonPolymorphic(UnknownDerivedTypeHandling = FallBackToBaseType or FallBackToNearestAncestor)]
        if (typeInfo.PolymorphismOptions == null)
        {
            typeInfo.PolymorphismOptions = new() { DerivedTypes = { new(typeInfo.Type) } };
            // TODO: decide whether to fail serialization even for types marked with
            // [JsonPolymorphic(UnknownDerivedTypeHandling = FallBackToBaseType or FallBackToNearestAncestor)]
            // If so, move the setting of UnknownDerivedTypeHandling out of this if statement.
            typeInfo.PolymorphismOptions.UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization;
        };
    };
}

然后设置选项,例如,如下所示:

var options = new JsonSerializerOptions()
{
    // Configure either a DefaultJsonTypeInfoResolver or some JsonSerializerContext and add the required modifier:
    TypeInfoResolver = new DefaultJsonTypeInfoResolver() 
        .WithAddedModifier(JsonExtensions.SetupUnknownDerivedTypeHandling()),
    // Set other options as required.
};

备注:

  • 因为System.Text.Json总是为声明为object的引用序列化完整的具体类型,所以在这种情况下我不会抛出异常.

  • 多态类型可以为JsonPolymorphicAttribute.UnknownDerivedTypeHandling配置特定的行为,其中FailSerialization是默认行为.来自docs家的:

    JsonUnknownDerivedTypeHandling value Effect
    FailSerialization An object of undeclared runtime type will fail polymorphic serialization. The default.
    FallBackToBaseType An object of undeclared runtime type will fall back to the serialization contract of the base type.
    FallBackToNearestAncestor An object of undeclared runtime type will revert to the serialization contract of the nearest declared ancestor type. Certain interface hierarchies are not supported due to diamond ambiguity constraints.

    如果您的某些类型的静态配置行为不是FailSerialization,而您想要覆盖它,则可以通过将该设置移到if (typeInfo.PolymorphismOptions == null)判断之外来执行此操作.

  • 就我个人而言,我不建议意外的集合或字典类型导致序列化失败.将属性声明为IList<T>IDictionary<TKey,TValue>并使用某些具体类型实现属性是很常见的.如果通过objectsOnly = false,则在这种情况下将抛出异常.

演示小提琴here.

Csharp相关问答推荐

如何使用PDFSharp将文本添加到现有PDF

当MD5被废弃时,如何在Blazor WASM中使用它?

如何使用C#和Graph API从Azure Directory获取用户详细信息

限制特定REST API不被访问,但部署代码

ASP.NET核心REST API返回一个非常大的数字

C#EF Core WHERE IN LINQ FROM LIST WITH.CONTAINS不返回任何内容

实体框架核心中的ComplexType和OwnsOne有什么不同?

异步实体框架核心查询引发InvalidOperation异常

如何使用自定义负载均衡器管理Ocelot负载均衡器中的多线程和批读取

如何使用MailKit删除邮箱?

具有以接口为其类型的属性的接口;类指定接口的实现,但无效

DateTime ToString()未以指定格式打印

EF核心新验证属性`DeniedValues`和`StringCompison`不起作用

如何在GRPC代码First服务的返回类型上使用多态性?

如何在同一成员上组合[JsonPropertyName]和[ObservableProperty]?

单元测试类型为HttpClient with Microsoft.Extensions.Http.Resilience

WPF:如何从DatagridHeader的内容模板绑定到词典项

根据优先级整理合同列表

在C#中通过Matheval使用自定义公式

.NET文档对继承的困惑