【问题标题】:Can Json.Net cast a deserialized object to the type embedded in the Json?Json.Net 可以将反序列化的对象转换为嵌入在 Json 中的类型吗?
【发布时间】:2019-03-19 15:21:34
【问题描述】:

上下文:我正在将数据序列化到消息队列中。消息队列将接受需要由接收方反序列化的异构类型。

问题:通常在反序列化时,我会使用如下代码: JsonConvert.DeserializeObject<Type>(object); 但是,由于类型是异构的,我不会提前知道所需的类型。

我知道我可以使用 TypeNameHandling 将类型嵌入到 JSON 中,但是在调用 DeserializeObject 时,我仍然没有得到强类型化的结果(例如,返回的对象尚未转换为嵌入的类型)。

问题:Json.Net 能否将反序列化的对象强制转换为嵌入在 Json 中的类型?如果没有,我最好的选择是从 JSON 中获取类型,然后调用 DeserializeObject 以便可以转换对象吗?

【问题讨论】:

  • 我的类型不共享一个基类,你需要手动反序列化你需要的每一个类型。您可以使用 JSON 中的类型名称使其“智能”。或者,您可以添加虚拟公共基类。 TypeNameHandling 允许您这样做:{circle, rect, triangle}.DeserializeObject<Shape>()
  • 一个选项可能是将其反序列化为动态类型,然后检查类型,也许
  • 在调用 DeserializeObject 时,我仍然没有得到强类型结果 -- 你能为此分享一个minimal reproducible example 吗?返回的对象的实际类型应该是"$type" 属性中指定的类型。之后,您只需执行object.GetType() 即可确定实际类型。

标签: c# json json.net


【解决方案1】:

您可以将类型(类)名称嵌入到您的数据中。反序列化的时候可以使用一点点反射和JsonConvert.DeserializeObject(string, Type):

string typeName; //Got from message
string json; //Got from message
Type type = Type.GetType($"Namespace.{typeName}, MyAssembly");
var obj = JsonConvert.DeserializeObject(json, type);

【讨论】:

  • 请注意,这种方法会使应用程序容易受到各种类型和代码注入攻击,从而导致应用程序不安全。有关详细信息,请参阅 TypeNameHandling caution in Newtonsoft Jsonblackhat.com/docs/us-17/thursday/…。 (stackoverflow 问题与使用"$type" 属性的安全风险有关,但答案也适用于此处。)
  • 注意这一点很重要。在 OP 的情况下,这不是风险,因为他自己将消息写入队列,而我的回答假设消息类型出现在某个程序集“MyAssembly”中。
猜你喜欢
  • 2019-12-08
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
  • 1970-01-01
  • 2012-07-04
  • 1970-01-01
  • 2023-01-11
  • 1970-01-01
相关资源
最近更新 更多