I'm working on a C++17 project that uses protobuf for data serialization, but I come across a problem.
I tried to serialize an object defined in protobuf into std::string and the object has only one enum field, when accidentally the value of the field is set to 0, the function SerializeAsString() or SerializToString(std::string*) will return true but I always get an empty string.
I checked out google api reference but got nothing helpful, can any one help me? I wrote some code to illustrate the problem.
Suppose we want to define a kind of message in testProtobuf.proto
syntax = "proto3";
package pb;
message testPackage{
enum testEnums{
TEST_0=0;
TEST_1=1;
TEST_2=2;
}
testEnums enumValue=1;
}
I compile it using
protoc --cpp_out=./ testProtobuf.proto
And in testProtobuf.cpp we have:
#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;
}
Then we compile the files:
g++ testProtobuf.cpp testProtobuf.pb.cc -lprotobuf -lpthread -o test.exe
When running the executable, it prints out these with the first line left blank:
enumValue: TEST_1
enumValue: TEST_2
Success? 1, Length: 0
Success? 1, Length: 2
Success? 1, Length: 2
I doubt this has something to do with '\0', but I don't have a better idea to make it work. Even SerializeToArray() returns true and leave the buffer I passed in untouched. All I need is to get the serialized form of the object. Can any one help me? Great thanks!!
The version of protoc is 3.6.1, the version of g++ is 9.3.0, and the host system is Ubuntu 20.04.3
This is actually not a problem at all since the parsing will work as expected because this is part of how protobuf
handles default values:
Also note that if a scalar message field is set to its default, the value will not be serialized on the wire.
So because protobuf
does not differentiate between a field being set to its default value and a field not being set at all, it simply does not serialize default values and your string is empty in this case.
Also this does not apply for enums
alone but for all scalar types:
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;
will also result in an empty serialized string but still gets correctly parsed:
Success? 1, Length: 0
Parsed: 0