FlatBuffers 转换数据字节为JSON字符串的格式。

flatbuffers::Parser::Parse 函数

parser->opts.strict_json = true; 置为JSON格式。

头文件:

cpp 复制代码
#pragma once

#include "prerequisites.h"
#include "msg_define_generated.h"
#include "LoggerManager.h"

class MessageDefine final : private boost::noncopyable
{
public:
	MessageDefine() = default;

	~MessageDefine() = default;

	static MessageDefine* instance();

	void initialize();

	std::shared_ptr<flatbuffers::Parser> findSchema(const std::string& name);
	std::shared_ptr<flatbuffers::Parser> findRequestSchema(MSG_DEFINE id);
	std::shared_ptr<flatbuffers::Parser> findReplySchema(MSG_DEFINE id);

	template<typename T>
	inline const T* parseRequestMessage(MSG_DEFINE id, std::string& message, size_t offset)
	{
		if (message.size() <= offset)
		{
			LOG_WARNING(default, "Schema size < offset, id[{}]", EnumNameMSG_DEFINE(id));
			return nullptr;
		}

		auto parser = MessageDefine::instance()->findRequestSchema(id);
		if (!parser)
		{
			LOG_WARNING(default, "Schema not find, id[{}]", EnumNameMSG_DEFINE(id));
			return nullptr;
		}

		if (!parser->Parse(message.c_str() + offset, nullptr))
		{
			LOG_WARNING(default, "Schema parse failed:{}, id[{}], error:{}", message, EnumNameMSG_DEFINE(id), parser->error_);
			return nullptr;
		}

		flatbuffers::Verifier verifier(parser->builder_.GetBufferPointer(), parser->builder_.GetSize());
		if (verifier.VerifyBuffer<T>(nullptr))
		{
			message.resize(parser->builder_.GetSize() + offset);
			memcpy((char*)(message.c_str() + offset), parser->builder_.GetBufferPointer(), parser->builder_.GetSize());
			return flatbuffers::GetRoot<T>(message.c_str() + offset);
		}
		return nullptr;
	}

	template<typename T>
	inline const T* parseReplyMessage(MSG_DEFINE id, std::string& message, size_t offset)
	{
		if (message.size() <= offset)
		{
			LOG_WARNING(default, "Schema size < offset, id[{}]", EnumNameMSG_DEFINE(id));
			return nullptr;
		}

		auto parser = MessageDefine::instance()->findReplySchema(id);
		if (!parser)
		{
			LOG_WARNING(default, "Schema not find, id[{}]", EnumNameMSG_DEFINE(id));
			return nullptr;
		}

		if (!parser->Parse(message.c_str() + offset, nullptr))
		{
			LOG_WARNING(default, "Schema parse failed:{}, id[{}]", message, EnumNameMSG_DEFINE(id));
			return nullptr;
		}

		flatbuffers::Verifier verifier(parser->builder_.GetBufferPointer(), parser->builder_.GetSize());
		if (verifier.VerifyBuffer<T>(nullptr))
		{
			message.resize(parser->builder_.GetSize() + offset);
			memcpy((char*)(message.c_str() + offset), parser->builder_.GetBufferPointer(), parser->builder_.GetSize());
			return flatbuffers::GetRoot<T>(message.c_str() + offset);
		}
		return nullptr;
	}
protected:
	bool loadSchemaFile(std::string_view path, const std::string& filename, bool bStrict);

protected:
	std::unordered_map<std::string, std::shared_ptr<flatbuffers::Parser>> m_parsers;
	std::unordered_map<MSG_DEFINE, std::string> m_requestIdNames;
	std::unordered_map<MSG_DEFINE, std::string> m_replyIdNames;
};


template<typename T>
inline const T* json2fb(const std::string& name, const char* message, std::string_view* outMessage)
{
	auto parser = MessageDefine::instance()->findSchema(name);
	if (!parser)
	{
		LOG_WARNING(default, "Schema:{} not find", name);
		return nullptr;
	}

	if (!parser->Parse(message, nullptr))
	{
		LOG_WARNING(default, "Schema:{} parse failed:{}", name, message);
		return nullptr;
	}

	flatbuffers::Verifier verifier(parser->builder_.GetBufferPointer(), parser->builder_.GetSize());
	if (verifier.VerifyBuffer<T>(nullptr))
	{
		if (outMessage)
			*outMessage = std::string_view(reinterpret_cast<char*>(parser->builder_.GetBufferPointer()), parser->builder_.GetSize());
		return flatbuffers::GetRoot<T>(parser->builder_.GetBufferPointer());
	}
	return nullptr;
}

inline bool bin2json(const std::string& name, const void* message, std::string& jsongen)
{
	auto parser = MessageDefine::instance()->findSchema(name);
	if (!parser)
	{
		LOG_WARNING(default, "Schema:{} not find", name);
		return false;
	}

	if (!GenerateText(*parser, message, &jsongen))
	{
		LOG_WARNING(default, "Schema:{} Couldn't serialize parsed data to JSON", name);
		return false;
	}
	return true;
}

源文件:

cpp 复制代码
#include "MessageDefine.h"
#include "ConfigLoader.h"
#include "MessageDefineConfig_generated.h"

MessageDefine* MessageDefine::instance()
{
	thread_local std::unique_ptr<MessageDefine> tl_instance;
	if (!tl_instance)
	{
		tl_instance = std::make_unique<MessageDefine>();
		tl_instance->initialize();
	}
	return tl_instance.get();
}

void MessageDefine::initialize()
{
	TConfigLoader<MessageDefineConfig> cfgMessageDefine;
	if (!cfgMessageDefine.parse("common/MessageDefineConfig.fbs", "config/MessageDefineConfig.json"))
	{
		return;
	}

	auto cfg = cfgMessageDefine.data;
	for (auto item : *cfg->items())
	{
		auto path = item->path()->string_view();
		if (item->names())
		{
			for (auto name : *item->names())
			{
				loadSchemaFile(path, name->str(), true);
			}
		}
		if (item->no_strict_names())
		{
			for (auto name : *item->no_strict_names())
			{
				loadSchemaFile(path, name->str(), false);
			}
		}
	}
	for (auto item : *cfg->request_id_names())
	{
		m_requestIdNames[item->id()] = item->name()->str();
	}
	for (auto item : *cfg->reply_id_names())
	{
		m_replyIdNames[item->id()] = item->name()->str();
	}
}

bool MessageDefine::loadSchemaFile(std::string_view path, const std::string& filename, bool bStrict)
{
	if (m_parsers.find(filename) != m_parsers.end())
		return true;

	// load FlatBuffer schema (.fbs)
	std::string schemafile;
	std::string schemafilename = fmt::format(path, filename);
	bool ok = flatbuffers::LoadFile(schemafilename.c_str(), false, &schemafile);
	if (!ok)
	{
		LOG_ERROR(network, "couldn't load schemafilename:{}", filename);
		return false;
	}

	// parse schema first, so we can use it to parse the data after
	auto parser = std::make_shared<flatbuffers::Parser>();
	const char* include_directories[] = { "../../fbs", nullptr };
	ok = parser->Parse(schemafile.c_str(), include_directories);
	if (!ok)
	{
		LOG_ERROR(network, "parse schemafilename:{} failed: {}", filename, parser->error_);
		return false;
	}

	if (bStrict)
	{
		parser->opts.strict_json = true;
	}

	m_parsers.emplace(filename, parser);
	return true;
}

std::shared_ptr<flatbuffers::Parser> MessageDefine::findSchema(const std::string& name)
{
	if (auto it = m_parsers.find(name); it != m_parsers.end())
	{
		it->second->builder_.Clear();
		return it->second;
	}
	return nullptr;
}

std::shared_ptr<flatbuffers::Parser> MessageDefine::findRequestSchema(MSG_DEFINE id)
{
	if (auto it = m_requestIdNames.find(id); it != m_requestIdNames.end())
	{
		return findSchema(it->second);
	}
	return nullptr;
}

std::shared_ptr<flatbuffers::Parser> MessageDefine::findReplySchema(MSG_DEFINE id)
{
	if (auto it = m_replyIdNames.find(id); it != m_replyIdNames.end())
	{
		return findSchema(it->second);
	}
	return nullptr;
}
相关推荐
牛奶咖啡131 小时前
Linux系统的常用操作命令——文件远程传输、文件编辑、软件安装的四种方式
运维·服务器·软件安装·linux云计算·scp文件远程传输·vi文件编辑·设置yum的阿里云源
weixin_437398211 小时前
转Go学习笔记(2)进阶
服务器·笔记·后端·学习·架构·golang
百锦再1 小时前
.Net配置文件appsetting.json的几种读取方法
chrome·json·.net·依赖注入·appsetting·web.config
tan77º2 小时前
【Linux网络编程】Socket - UDP
linux·服务器·网络·c++·udp
szxinmai主板定制专家4 小时前
【精密测量】基于ARM+FPGA的多路光栅信号采集方案
服务器·arm开发·人工智能·嵌入式硬件·fpga开发
Paper_Love4 小时前
x86-64_windows交叉编译arm_linux程序
arm开发·windows
你不知道我是谁?4 小时前
负载均衡--四层、七层负载均衡的区别
运维·服务器·负载均衡
前端若水4 小时前
通过 Windows 共享文件夹 + 手机访问(SMB协议)如何实现
windows·智能手机
九丝城主5 小时前
2025使用VM虚拟机安装配置Macos苹果系统下Flutter开发环境保姆级教程--中篇
服务器·flutter·macos·vmware
码出钞能力5 小时前
linux内核模块的查看
linux·运维·服务器