C# JSON.NET 反序列化为带有 Type 参数的对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15178323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 14:22:01  来源:igfitidea点击:

JSON.NET deserialize to object with Type parameter

c#typescastingjson.netdeserialization

提问by avanwieringen

I have the following problem which I am unable to solve:

我有以下问题无法解决:

I have different classes which all implement an interface named IProtocol. The are named, for now, SimpleProtocol, ParallelProtocol. I wanted to persist those object so I used JSON.NET and everything works fine. Except when I am trying to deserialize them it works perfectly when I know the type they are supposed to be, for instance:

我有不同的类,它们都实现了一个名为IProtocol. 目前,它们被命名为SimpleProtocolParallelProtocol。我想保留这些对象,所以我使用了 JSON.NET 并且一切正常。除了当我试图反序列化它们时,当我知道它们应该是什么类型时,它可以完美地工作,例如:

SimpleProtocol p = JsonConvert.DeserializeObject<SimpleProtocol>(myJsonData);

However, I am now in a situation where I want to load the JSON data and get an IProtocolback, but that is, understandably, not allowed by JSON; E.g., something like this does notwork:

但是,我现在处于一种情况,我想加载 JSON 数据并IProtocol返回,但可以理解的是,JSON 不允许;例如,这样的事情并没有工作:

IProtocol p1 = JsonConvert.DeserializeObject<IProtocol>(myJsonData); // does not work
IProtocol p2 = (IProtocol)JsonConvert.DeserializeObject(myJsonData); // also, does not work

So, looking up the APII found this method signature:

所以,查找API我发现了这个方法签名:

public static Object DeserializeObject(
    string value,
    Type type
)

which looks just like the thing I needed, so trying out by also persisting the type in a string and retrieving it:

这看起来就像我需要的东西,所以通过将类型保存在字符串中并检索它来尝试:

// test
Type protocolType = Type.GetType("MyApp.Protocols.SimpleProtocol");
IProtocol p1 = JsonConvert.DeserializeObject(myJsonData, protocolType);

I get an error that it is impossible to cast a Newtonsoft.Json.Linq.JObjectto IProtocol. This is weird and I don't know how to solve this.

我收到一个错误,无法将 a 转换Newtonsoft.Json.Linq.JObjectIProtocol. 这很奇怪,我不知道如何解决这个问题。

It is impossible to pass the Type object in a generic method, so I am basically stuck here. Is there a method to solve this, preferably without using Reflection? It looks to me that this is a perfectly normal use case.

在泛型方法中传递Type对象是不可能的,所以我基本上卡在这里了。有没有办法解决这个问题,最好不使用反射?在我看来,这是一个完全正常的用例。

What I can do, but it seems a bit 'dirty' to me, is to create a simple wrapper class which holds an IProtocol instance in it and serialize / deserialize that?

我能做什么,但对我来说似乎有点“脏”,是创建一个简单的包装类,其中包含一个 IProtocol 实例并序列化/反序列化它?

采纳答案by avanwieringen

It seemed that my initial approach by using this method was correct after all:

看来我最初使用这种方法的方法毕竟是正确的:

public static Object DeserializeObject(
    string value,
    Type type
)

The problem was that I persisted my object type as using MyProtocol.GetType().FullNamewhich resulted in a value following from

问题是我坚持使用我的对象类型,MyProtocol.GetType().FullName这导致了一个值来自

Type protocolType = Type.GetType(PersistedTypeString);

Type protocolType = Type.GetType(PersistedTypeString);

to be a Type with nullvalues. However by using MyProtocol.GetType().AssemblyQualifiedNameeverything works just fine (p.s. this is also included in the docs of Type.GetType())

成为具有null值的类型。然而,通过使用MyProtocol.GetType().AssemblyQualifiedName一切正常(ps 这也包含在 Type.GetType() 的文档中)

Here is my code sample:

这是我的代码示例:

Type ProtocolType = Type.GetType(MetaData["ProtocolType"]);
var Protocol = JsonConvert.DeserializeObject(Data["Protocol"], 
                                             ProtocolType, 
                                             JsonProtocolPersister.DefaultSettings);
return (IProtocol)Protocol;