反序列化泛型类型

时间:2017-10-12 16:57:57

标签: c# generics serialization json.net

我有一个通用类型Container<IContentType>,其中接口IContentType可以是四种具体的ContentX类型之一。

我序列化,一切都很好。

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

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

但是,如果我在这样的方法中这样做:

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

我得到&#34;无法隐式地将Container<ContentA>转换为Container<IContentType>&#34;。 ContentA实施IContentType

有没有办法可以创建转换操作符,转换,动态或使隐式转换工作?

1 个答案:

答案 0 :(得分:3)

您应该使用预先加载JSON的custom JsonConverter反序列化Container<ContentX>,而不是尝试将X反序列化为具体类型Container<IContentType>。进入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