c# - 反序列化泛型类型

标签 c# generics serialization json.net

我有一个通用类型 Container<IContentType>接口(interface)在哪里IContentType可以是四个具体之一ContentX类型。

我序列化了,一切都很好。

使用 Newtonsoft 反序列化时,我使用自定义类型转换器和 var model = JsonConvert.DeserializeObject<Container<ContentA>>(json, settings)作品。调试器显示我有一个 Container<ContentA>对象。

我的计划是在反序列化时尝试对四种可能的 ContentX 中的每一个进行反序列化。类型并默默地捕获异常,直到我“猜出”正确的异常。

但是,如果我在这样的方法中执行此操作:

public static Container<IContentType> Deserialize(jsonfile)
{
    ...
    var model = JsonConvert.DeserializeObject<Container<ContentA>>(json, settings)
    return model;
}

我收到“无法将 Container<ContentA> 隐式转换为 Container<IContentType>”。 ContentA实现IContentType .

有没有办法可以创建强制转换运算符、转换、动态或使隐式转换起作用?

最佳答案

而不是尝试反序列化为 Container<ContentX>适用于混凝土类型 X ,您应该反序列化为 Container<IContentType>使用custom JsonConverter 将 JSON 预加载到 JToken 中并按照 How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects? 推断具体类型或Deserializing polymorphic json classes without type information using json.netJson.Net Serialization of Type with Polymorphic Child Object .

因此您的转换器将类似于:

public class ContentConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(IContentType);
    }

    Type GetConcreteType(JObject obj)
    {
        if (obj.GetValue(nameof(ContentA.SomePropertyOfContentA), StringComparison.OrdinalIgnoreCase) != null)
            return typeof(ContentA);
        // Add other tests for other content types.
        // Return a default type or throw an exception if a unique type cannot be found.
        throw new JsonSerializationException("Cannot determine concrete type for IContentType");
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var obj = JObject.Load(reader);
        var concreteType = GetConcreteType(obj);
        return obj.ToObject(concreteType, serializer);
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

您可以调用 JsonConvert看起来像:

var settings = new JsonSerializerSettings
{
    Converters = { new ContentConverter() },
};
var model = JsonConvert.DeserializeObject<Container<IContentType>>(json, settings);

最后,您可以使用完全自动选择类型

new JsonDerivedTypeConverer<IContentType>(typeof(ContentA), typeof(ContentB), typeof(ContentC), typeof(ContentD))

哪里JsonDerivedTypeConverer<T>取自JsonConverter with Interface .

关于c# - 反序列化泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46715112/

相关文章:

c# - 根据 Text 的值更改 TextBlock 背景

c# - 如何在外部浏览器中打开 webBrowser 控件中的链接?

c# - 如何使用 Unity 将通用接口(interface)自动注册到该接口(interface)的非通用实现

java - 使用 Java 8 为 Gson 编写序列化程序

serialization - Ansible:无法为顺序执行设置变量

python - Django Rest Framework 不序列化 SerializerMethodField

c# - EF Core 和封装的集合

c# - 如何在 c# 中模拟鼠标点击,这将在游戏中起作用?

c# - 通过 for 语句循环遍历 System.Collections.Generic.Dictionary

c++ - 在通用容器中查找特定实现