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 do
    std::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 section
        parser.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.

  1. https://github.com/google/flatbuffers/tree/master
  2. https://stackoverflow.com/questions/60176212/serializing-a-flatbuffer-object-to-json-without-its-schema-file
  3. https://dbaileychess.github.io/flatbuffers/flatbuffers_guide_using_schema_compiler.html
  4. https://flatbuffers.dev/languages/cpp/#mini-reflection
相关推荐
旖-旎14 小时前
深搜练习(组合总和)(7)
c++·算法·深度优先·力扣
T0uken14 小时前
基于 vcpkg 与 LLVM-MinGW 的 Qt6 静态链接开发方案
c++·windows·qt
睡一觉就好了。14 小时前
C++11(一)
c++
csbysj202014 小时前
Java 条件语句
开发语言
水云桐程序员14 小时前
C++的主要应用场景
c++·学习方法
Ulyanov15 小时前
《现代 Python 桌面应用架构实战:PySide6 + QML 从入门到工程化》 开发环境搭建与工具链极简主义 —— 拒绝臃肿,构建工业级基座
开发语言·python·qt·ui·架构·系统仿真
逻辑驱动的ken15 小时前
Java高频面试场景题19
java·开发语言·面试·职场和发展·求职招聘
初心未改HD15 小时前
Go语言net/http与Web开发:构建高性能HTTP服务
开发语言·golang
叼烟扛炮15 小时前
C++第一讲:C++ 入门基础
开发语言·c++·函数重载·引用·内联函数·nullptr
Ulyanov16 小时前
《现代 Python 桌面应用架构实战:PySide6 + QML 从入门到工程化》:QML 声明式语法与霓虹按钮 —— 当 Python 遇见现代美学
开发语言·python·ui·qml·系统仿真·雷达电子对抗仿真