Protobuf枚举值无法通过TextFormat序列化到prototxt,如何解决?
问题:Protobuf TextFormat序列化时枚举值未输出
我使用google::protobuf::TextFormat::Print可以成功将其他字段序列化为ASCII格式,但枚举值未在输出的prototxt文件中显示。相关代码如下:
main.cpp
#include <iostream> #include <filesystem> #include <fcntl.h> #include <unistd.h> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/text_format.h> #include "example.pb.h" bool pb_SaveToFile( const std::filesystem::path File, const google::protobuf::Message &Message ) { int fd = open ( File.string ( ).c_str ( ), O_WRONLY | O_CREAT | O_TRUNC, 0666 ); if ( fd == - 1 ) { return false; } google::protobuf::io::FileOutputStream * output = new google::protobuf::io::FileOutputStream ( fd ); bool success = google::protobuf::TextFormat::Print ( Message, output ); delete output; close ( fd ); return success; } int main(int argc, char *argv[]) { std::filesystem::path fullPath = "saved.prototxt"; pbtest::PbTestMessage tm; // Timestamp auto ts = tm.mutable_timestamptest(); ts->set_seconds(time(NULL)); ts->set_nanos(0); // Enum tm.set_enumtest(::pbtest::enumTestValues::ENUM_ZERO); // String tm.set_stringtest("string test!"); // Save it pb_SaveToFile(fullPath, tm); std::cout << "Done!" << std::endl; return 0; }
example.proto
syntax = "proto3"; import "google/protobuf/timestamp.proto"; package pbtest; enum enumTestValues { ENUM_ZERO = 0; ENUM_ONE = 1; } message PbTestMessage { google.protobuf.Timestamp timestampTest = 1; enumTestValues enumTest = 2; string stringTest = 3; }
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.9) project (protobuf-example) find_package(Protobuf REQUIRED) include_directories(${Protobuf_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS example.proto) add_executable(protobuf-example main.cpp ${PROTO_SRCS} ${PROTO_HDRS}) target_link_libraries(protobuf-example ${Protobuf_LIBRARIES}) target_compile_features(protobuf-example PRIVATE cxx_std_17)
运行后saved.prototxt内容:
timestampTest { seconds: 1673886921 } stringTest: "string test!"
请问如何让枚举值保存到prototxt文件中?
解决方案
问题根源是Proto3的默认行为:默认值字段不会被序列化输出。你设置的ENUM_ZERO值为0,是该枚举类型的默认值,所以TextFormat::Print默认不会输出这个字段。
要输出默认值字段,需要使用google::protobuf::TextFormat::Printer并开启print_default_values选项,修改pb_SaveToFile函数即可:
bool pb_SaveToFile( const std::filesystem::path File, const google::protobuf::Message &Message ) { int fd = open ( File.string ( ).c_str ( ), O_WRONLY | O_CREAT | O_TRUNC, 0666 ); if ( fd == - 1 ) { return false; } google::protobuf::io::FileOutputStream * output = new google::protobuf::io::FileOutputStream ( fd ); google::protobuf::TextFormat::Printer printer; // 开启输出默认值字段的选项 printer.SetPrintDefaultValues(true); bool success = printer.Print(Message, output); delete output; close ( fd ); return success; }
修改后重新编译运行,saved.prototxt就会包含枚举字段:
timestampTest { seconds: 1673886921 } enumTest: ENUM_ZERO stringTest: "string test!"
另外,如果你不想输出所有默认值,只是想输出这个枚举的0值,也可以考虑将枚举的默认值改为其他值(比如把ENUM_ONE设为0),但这种方式会改变业务逻辑,不推荐除非有特殊需求。
内容的提问来源于stack exchange,提问作者Brian
相关产品推荐
相关产品推荐

