反序列化一个通用类型

反序列化一个通用类型

问题描述:

我有一个通用类型Container<IContentType>其中接口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

有没有一种方法可以创建一个演员操作,转换,动态或使隐式转换工作?

+0

为什么不只是'JsonConvert.DeserializeObject >(json,settings)作为Container '? –

+0

您已遇到差异问题。例如,即使'string'是'object'的子类,你不能将'List '强制转换为'List ',因为那么'List '引用将会有一个方法'Add(Object)',这对于引用“指向”的实际“列表”不适用。 –

+2

您将需要为'IContentType'创建一个自定义的'JsonConverter',并按照[如何在JSON.NET中实现自定义JsonConverter来反序列化基类对象的列表]这两行来推断正确的具体类型?](https:// *.com/q/8030538/3744182)或[使用json.net反序列化没有类型信息的多态json类](https://*.com/q/19307752/3744182)或[Json.Net带多形子类型的序列化对象(https://*.com/q/29528648/3744182)。然后你可以反序列化到'Container '。 – dbc

而不是试图反序列化作为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.net线具体类型反序列化或Json.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