C++中将FlatBuffers序列化为JSON
FlatBuffers是google发布的一个高效的序列化库,最近需要将系统中的flatbuffer的二进制数据转换为JSON以便其他系统使用,发现flatbuffer原生支持与JSON结构之间的转换。
方法一:使用GenerateText()函数
加载schema文件内容构造flatbuffers::Parser解析器,最后通过GenerateText()函数解析为JSON字符串。stackoverflow中有一段代码贴来,示例如下:
bool MyFBSchemaWrapper::asJson(std::string& jsonOutput)
{//**This is the section I don't like having to dostd::string schemaFile;if (flatbuffers::LoadFile((std::string(getenv("FBS_FILE_PATH")) + "MyFBSchema.fbs").c_str(), false, &schemaFile)){flatbuffers::Parser parser;const char *includePaths[] = { getenv("FBS_FILE_PATH");parser.Parse(schemaFile.c_str(), includePaths);//**End bad sectionparser.opts.strict_json = true;flatbuffers::FlatBufferBuilder fbBuilder;auto testItem1 = fbBuilder.CreateString("test1");auto testItem2 = fbBuilder.CreateString("test2");MyFBSchemaBuilder myBuilder(fbBuilder);myBuilder.add_item1(testItem1);myBuilder.add_item2(testItem2);FinishMyFBSchemaBuffer(fbBuilder, myBuilder.finish());auto result = GenerateText(parser, fbBuilder.GetBufferPointer(), &jsonOutput);return true;}return false;
}
其中:Parser和GenerateText都定义在在flatbuferrs/idl.h中,如下:
// Parse the string containing either schema or JSON data, which will// populate the SymbolTable's or the FlatBufferBuilder above.// include_paths is used to resolve any include statements, and typically// should at least include the project path (where you loaded source_ from).// include_paths must be nullptr terminated if specified.// If include_paths is nullptr, it will attempt to load from the current// directory.// If the source was loaded from a file and isn't an include file,// supply its name in source_filename.// All paths specified in this call must be in posix format, if you accept// paths from user input, please call PosixPath on them first.bool Parse(const char* _source, const char** include_paths = nullptr,const char* source_filename = nullptr);
// Generate text (JSON) from a given FlatBuffer, and a given Parser
// object that has been populated with the corresponding schema.
// If ident_step is 0, no indentation will be generated. Additionally,
// if it is less than 0, no linefeeds will be generated either.
// See idl_gen_text.cpp.
// strict_json adds "quotes" around field names if true.
// These functions return nullptr on success, or an error string,
// which may happen if the flatbuffer cannot be encoded in JSON (e.g.,
// it contains non-UTF-8 byte arrays in String values).
extern bool GenerateTextFromTable(const Parser& parser, const void* table,const std::string& tablename,std::string* text);
extern const char* GenerateText(const Parser& parser, const void* flatbuffer,std::string* text);
extern const char* GenerateTextFile(const Parser& parser,const std::string& path,const std::string& file_name);
方法二:使用FlatBuffers中提供的mini reflection机制
这种方法要加上参数(–reflect-types)重新编译头文件,如:
# 将原来的命令(flatc -o ./ -cpp *.fbs)加上--reflect-types
flatc -o ./ --reflect-types -cpp *.fbs
使用FlatBufferToString函数
FlatBufferToString()函数定义在flatbuferrs/minireflect.h中,如下:
inline std::string FlatBufferToString(const uint8_t* buffer,const TypeTable* type_table,bool multi_line = false,bool vector_delimited = true,const std::string& indent = "",bool quotes = false) {ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", quotes, indent,vector_delimited);IterateFlatBuffer(buffer, type_table, &tostring_visitor);return tostring_visitor.s;
}
REF.
- https://github.com/google/flatbuffers/tree/master
- https://stackoverflow.com/questions/60176212/serializing-a-flatbuffer-object-to-json-without-its-schema-file
- https://dbaileychess.github.io/flatbuffers/flatbuffers_guide_using_schema_compiler.html
- https://flatbuffers.dev/languages/cpp/#mini-reflection
