protobuf 是结构化数据的系列化/反序列化解决方案,类似XML/JSON,但他的运行效率及压缩率均较后者高一个数量级,且完全的跨平台。使用步骤如下:
1、定义一个.proto数据结构文件,如test.proto:
syntax = "proto3";
package google.protobuf;
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
option cc_enable_arenas = true;
option go_package = "google.golang.org/protobuf/types/known/testpb";
option java_package = "com.google.protobuf";
option java_outer_classname = "TestProto";
option java_multiple_files = true;
option objc_class_prefix = "GPB";
// `Test` represents a structured data value, consisting of fields
// which map to dynamically typed values. In some languages, `Test`
// might be supported by a native representation. For example, in
// scripting languages like JS a struct is represented as an
// object. The details of that representation are described together
// with the proto support for the language.
//
// The JSON representation for `Test` is JSON object.
message Test {
// Unordered map of dynamically typed values.
map<string, TestValue> fields = 1;
}
// `Value` represents a dynamically typed value which can be either
// null, a number, a string, a boolean, a recursive struct value, or a
// list of values. A producer of value is expected to set one of that
// variants, absence of any variant indicates an error.
//
// The JSON representation for `Value` is JSON value.
message TestValue {
// The kind of value.
oneof kind {
// Represents a null value.
TestNullValue null_value = 1;
// Represents a double value.
double number_value = 2;
// Represents a string value.
string string_value = 3;
// Represents a boolean value.
bool bool_value = 4;
// Represents a structured value.
Test struct_value = 5;
// Represents a repeated `Value`.
TestListValue list_value = 6;
}
}
// `NullValue` is a singleton enumeration to represent the null value for the
// `Value` type union.
//
// The JSON representation for `NullValue` is JSON `null`.
enum TestNullValue {
// Null value.
NULL_VALUE = 0;
}
// `ListValue` is a wrapper around a repeated field of values.
//
// The JSON representation for `ListValue` is JSON array.
message TestListValue {
// Repeated field of dynamically typed values.
repeated TestValue values = 1;
}
2、使用protoc命令(自行安装或源码编译)将上述文件编译成各种平台代码,这里以C++为例:
./protoc --cpp_out=. test.proto
执行后,会生成test.pb.h 及 test.pb.cc 两个代码文件,其他语言也会生成相应的代码。
3、添加测试代码测试结构体数据的序列化及反序列化:
/*
* misc_test.cc
*
* Created on: Jun 27, 2021
* Author: root
*/
#include "../my_test.h"
#include "test.pb.h"
TEST(ProtobufTest, PackAndUnpack) {
// ------Serialize------
google::protobuf::TestValue msg_val;
msg_val.set_number_value(123.f);
std::string str = msg_val.SerializeAsString();
std::cout << "--------- len:" << str.length() << ":" << str << std::endl;
google::protobuf::Test message;
message.mutable_fields()->operator []("test") = msg_val;
str = message.SerializeAsString();
std::cout << "--------- len:" << str.length() << ":" << str << std::endl;
// -------DeSerialize------
google::protobuf::Test parsed_msg;
EXPECT_TRUE(parsed_msg.ParseFromString(str));
EXPECT_EQ(parsed_msg.fields_size(), 1);
EXPECT_EQ(parsed_msg.fields().begin()->first, "test");
EXPECT_EQ(parsed_msg.fields().begin()->second.number_value(), 123.f);
}
执行结果:
--------- len:9:(二进制数据打印不了)
--------- len:19:
(二进制数据打印不了)
End.