在 protobuf C++ 中处理枚举值 0

Handling enum value 0 in protobuf c++

我正在开发一个使用 protobuf 进行数据序列化的 C++17 项目,但我遇到了一个问题。
我试图将protobuf中定义的一个对象序列化为std::string并且该对象只有一个枚举字段,当不小心将该字段的值设置为0时,函数SerializeAsString()或SerializToString(std::string* ) 将 return true 但我总是得到一个空字符串。 我查看了 google api 参考资料,但没有任何帮助,有人可以帮助我吗?我写了一些代码来说明这个问题。

假设我们要在testProtobuf.proto

中定义一种消息
syntax = "proto3";
package pb;
message testPackage{
enum testEnums{
    TEST_0=0;
    TEST_1=1;
    TEST_2=2;
}
    testEnums enumValue=1;  
}

我使用

编译它
 protoc  --cpp_out=./ testProtobuf.proto 

在 testProtobuf.cpp 中我们有:

#include<iostream>
#include<string>
#include "testProtobuf.pb.h"

int main(){
    pb::testPackage t0,t1,t2;
    t0.set_enumvalue(pb::testPackage::TEST_0);
    t1.set_enumvalue(pb::testPackage::TEST_1);
    t2.set_enumvalue(pb::testPackage::TEST_2);
    std::cout<<t0.ShortDebugString()<<"\n"<<t1.ShortDebugString()<<"\n"<<t2.ShortDebugString()<<std::endl;
    std::string temp;
    std::cout<<"Success? "<<t0.SerializeToString(&temp)<<", Length: "<<temp.length()<<std::endl;
    std::cout<<"Success? "<<t1.SerializeToString(&temp)<<", Length: "<<temp.length()<<std::endl;
    std::cout<<"Success? "<<t2.SerializeToString(&temp)<<", Length: "<<temp.length()<<std::endl;
    return 0;
}

然后我们编译文件:

g++ testProtobuf.cpp testProtobuf.pb.cc -lprotobuf -lpthread -o test.exe

当运行可执行文件时,它打印出这些第一行留空

enumValue: TEST_1
enumValue: TEST_2
Success? 1, Length: 0
Success? 1, Length: 2
Success? 1, Length: 2

我怀疑这与“\0”有关,但我没有更好的办法让它发挥作用。 甚至 SerializeToArray() returns true 并且保持我传入的缓冲区不变。我只需要获取对象的序列化形式。谁能帮我?非常感谢!!

protoc版本为3.6.1,g++版本为9.3.0,主机系统为Ubuntu20.04.3

这实际上根本不是问题,因为解析将按预期工作,因为这是 protobuf 处理方式的一部分 default values:

Also note that if a scalar message field is set to its default, the value will not be serialized on the wire.

因此,因为 protobuf 不区分设置为其默认值的字段和根本未设置的字段,它根本不序列化默认值,并且在这种情况下您的字符串为空。

此外,这不仅适用于 enums,还适用于所有标量类型:

message testPackage2 {
    int32 intValue=1;
}

pb::testPackage2 in, out;
out.set_intvalue(0);
std::cout << "Success? " <<out.SerializeToString(&temp)<< ", Length: " << temp.length() << std::endl;
in.ParseFromString(temp);
std::cout<<"Parsed: " << in.intvalue() << std::endl;

也会产生一个空的序列化字符串,但仍能正确解析:

Success? 1, Length: 0
Parsed: 0