将Json JObject转换为派生类

时间:2016-07-01 19:50:46

标签: c# json reflection json.net

我有一个名为NProcess的抽象类,我将从中派生出许多不同的Process对象。

public abstract class NProcess
{   
    public ProcessConfigurations ProcessSettings { get; set; } 
}

ProcessessConfigutations类如下所示:

[Browsable(true)]
public abstract class ProcessConfigurations { }

从NProcess派生的对象示例是EmailReader, FileCopier or FTPProcess,....可以是任何内容,因此从ProcessConfigurations派生的属性类将具有一组仅与该过程相关的属性。

我可以使用Reflection加载从Nprocess派生的进程,当我选择一个属性网格中出现一组不同的属性时,如预期的那样。

我正在序列化设置并将它们作为BSON存储在数据库中。

问题:反序列化向我显示了Json字符串,但是我收到以下错误:

  

无法隐式转换类型' Newtonsoft.Json.Linq.JObject'至   ' ProcessConfigurations'

我需要能够将JObject转换或转换为任何动态类型派生自' ProcessConfigurations'但我无法得到派生类型。

1 个答案:

答案 0 :(得分:0)

如果每个配置都是不同的类,您如何知道它们从数据库出来时应该是什么类型?假设您查询数据库并返回

{ "SourceFullPath": "c\\Source", "Destination": "c:\\temp", "OnExists": 1 }

您不知道应该反序列化的具体类型。并且您不能将它填充到ProcessConfigurations类中,因为abstract类无法实例化(解串器将在概念上需要" new up"一个对象然后复制将JSON属性放入其中)。

那你能做什么?

直接的答案是在序列化的Json中包含类型信息。 Json.Net有一个功能,它会自动为您执行此操作。它被称为TypeNameHandling。由此产生的Json看起来像:

{ "$type": "Your.Namespace.Here.MyConcreteProcessConfiguration, Your.Assembly.Here", "SourceFullPath": "c\\Source", "Destination": "c:\\temp", "OnExists": 1 }

然后,当它被反序列化时,Json.Net会知道哪个类型为" new up"。

如果您不想使用Json.Net内置的方式执行此操作,则必须将类型信息存储在您自己的字段中并编写自定义JsonConverter正如@JDB链接中提到的那样:JSON.NET deserialize to abstract class or interfaceJsonConverter基本上会做这样的事情来反序列化(取自上面的博客文章):

public class MyConverter : JsonConverter {

    // ... other stuff, see the blog article

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        if (jo["MyCustomType"].Value<string>() == "MyConcreteProcessConfiguration")
            return jo.ToObject<MyConcreteProcessConfiguration>(serializer);

        if (jo["MyCustomType"].Value<string>() == "MyOtherConcreteProcessConfiguration")
            return jo.ToObject<MyOtherConcreteProcessConfiguration>(serializer);

       return null;
    }
}