Qt 6.8 Protobuf 序列化默认值到 Json

问题描述 投票:0回答:1

我在原型文件中有一条消息

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 值。

c++ qt protocol-buffers
1个回答
0
投票

了解您正在使用的 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 生成的代码。它可能不会如此无缝地集成到开发项目中,但这可能是您必须做的才能让事情正常进行。

© www.soinside.com 2019 - 2024. All rights reserved.