无法将对象反序列化为其类,但只能作为其父类

Posted

技术标签:

【中文标题】无法将对象反序列化为其类,但只能作为其父类【英文标题】:Unable to deserialize object as its class, but only as its parent's 【发布时间】:2015-07-13 15:05:41 【问题描述】:

我有一个服务器接收使用 boost 序列化 text_archive 序列化的数据。到达的数据可以是以下MB_BPRequestMB_BPResponse之一,两者都扩展MB_BPMessage

所以我有这个代码:

request_callback(MB_BPRequest);
response_callback(MB_BPResponse);

try 
  MB_BPRequest req;
  archive >> req;
  request_callback_(req);

catch (std::exception& e) 
  MB_BPResponse resp;
  archive >> resp;
  response_callback_(resp);

奇怪的是,如果我使用基类,它只会反序列化存档:

  MB_BPMessage req;
  archive >> req;
  request_callback_(/*cast somehow*/req);

否则会引发“输入流错误”。

问题在于我不能将MB_BPMessage 转换为MB_BPRequestMB_BPResponse,因为编译器会抛出错误。

我有兴趣了解解决此问题的其他方法。

【问题讨论】:

【参考方案1】:

您只能通过指针(反)序列化多态类型。见

文档http://www.boost.org/doc/libs/1_58_0/libs/serialization/doc/serialization.html#derivedpointers

特别是如果你真的必须通过引用序列化这些,你将不得不手动处理所有权语义:

文档:http://www.boost.org/doc/libs/1_58_0/libs/serialization/doc/serialization.html#references

我们通过序列化引用来解决这些问题,就好像它们是指针一样。

【讨论】:

问题在于MB_BPRequestMB_BPResponse 实际上并不是多态的——它们只是与它们的基类MB_BPMessage 共享一些功能,但没有虚拟方法。跨度> @Mak 在这种情况下,您为什么期望能够提取与序列化不同的类型 (MB_BPMessage)?那只是一个错误。您可能想改用boost::variant<MB_BPRequest, MB_BPResponse> - 只要您序列化与反序列化相同的类型 对不起,如果我的问题不够清楚。当我序列化MB_BPRequest 时,我只能将其反序列化为MB_BPMessage,否则我会遇到异常。我会看 int boost::variant。谢谢 我认为我的评论是正确的。你只是没有显示序列化代码,但我敢打赌它序列化了MB_BPMessage...如果没有,请将相关代码添加到问题中(SSCCE) 下面是一个全面的示例,显示了可能出现的问题:Live On Coliru。还要注意不兼容的反序列化如何甚至不会引发错误(在这里它会默默地返回错误的结果)。 live-stream recording 仍然可用

以上是关于无法将对象反序列化为其类,但只能作为其父类的主要内容,如果未能解决你的问题,请参考以下文章

Boost 将派生类反序列化为基类指针

使用 JsonConvert.DeserializeObject 或 JObject.Parse 将类反序列化为 c# 中的字典

Jackson - 使用泛型类反序列化

PHP原生类反序列化

无法将 JSON 字符串反序列化为 C# 对象

将 JSON 命名属性反序列化为 .Net 对象