我在原型文件中有一条消息
message GeoCoord
{
double lat = 1;
double lon = 2;
}
将此消息序列化为 json 并在其他套接字上使用 WebSocket 发送它后,我在操作默认值时未设置值。
使用 Qt Protobuf 的常见情况:
QProtobufJsonSerializer serializer_json;
GeoCoord geo;
geo.setLat(1.1);
geo.setLon(2.2);
QByteArray message = geo.serialize(&serializer_json);
socket->send(message)
之后在另一个套接字中我们收到一条消息
{"geoCoords":{"lat":1.1,"lon":2.2}}
这就是我所期望的。但如果我尝试设置默认双值0
:
geo.setLat(0);
geo.setLon(0);
消息是
{"geoCoords":{}}
。如果我根本不设置它们就好了:
GeoCoord geo;
QByteArray message = geo.serialize(&serializer_json);
有正常的方法可以使用默认值进行操作吗?我知道对于 double 1 可以设置“-0”,但在其他消息中我有 int 值。
了解您正在使用的 Protobufs 版本会很有用:2 还是 3?
在版本 3 中,消息中的每个字段都是可选的。在您的情况下,这意味着将 lat 和 lon 设置为 0 的消息与从未设置它们的消息之间存在非常明显的差异。正如你所说,如果你根本不设置它们,输出是可以理解的。
所以,我认为您在别人的代码中遇到了错误。
看起来QT已经构建了自己的代码生成器。您是否在 cmake 中使用
qt_add_protobuf
来实现 QT,还是调用 qtprotobufgen
从 .proto 文件生成 QT 类?
要尝试的事情
1) 一个或两个字段?
尝试仅将 lat 设置为 0,看看会出现什么结果。
2)生成的代码理解选项字段?
查看 GeoCoord 类的生成代码会很有趣,看看这两个字段是否具有类似于
has_lat()
或 has_lon()
的方法或属性。此类方法将由 Google 协议的标准使用中的 C++ 代码生成器生成,并用于指示字段是否确实已设置。如果 QT 生成的代码有这样的方法,那么至少它知道这些字段是可选的。这反过来又会增加 QProtobufJsonSerializer
出现问题的可能性。
3) 与普通 Google 协议生成代码比较
将结果与使用 Google 的
protoc
生成其 C++ 类实现所获得的结果进行比较也会很有趣,看看其行为是否符合预期。
4) 使用普通 Google protoc 生成代码的其他原因
看起来 QT 无论如何都在使用这个,并添加了一个插件,我假设该插件是为了支持 QT 自己的数据类型,例如
QPoint
。我不知道他们为什么这样做; protobufs 的全部目的是允许不同平台上的不同语言之间进行数据交换,并且 QT 数据类型对 C++/QT 之外的任何东西都没有任何意义。 QT 已经拥有自己完全独立的序列化库,用于 QT-QT 互换。
我提到这一点是因为如果问题出在 QT 围绕 Google 的普通 C++ 实现的广泛包装器中,您可能可以“按原样”使用 Google 生成的代码。它可能不会如此无缝地集成到开发项目中,但这可能是您必须做的才能让事情正常进行。