C++ 轻量级对象JSON序列化实现详情
为什么需要JSON序列化
在程序开发过程中,我们通常需要将内存中的数据序列化并存储到文件或者网络中进行传输。JSON作为一种轻量级的数据交换格式,因其具有易读性、易存储、易解析等优点,被广泛应用于前后端数据交互、移动设备数据传输等领域。C++社区相关的JSON库也有很多,但有些过于庞大,并不适用于轻量级数据的处理。因此,我们需要一些轻量级的JSON序列化库。
序列化库的设计思路
本序列化库的设计有以下几个特点:
- 基于标准库实现,不需要任何第三方依赖。
- 支持JSON对象、JSON数组的序列化。
- 采用提取式编程风格,不使用反射技术,避免面向对象编程的性能开销。
- 具有高灵活性,支持自定义序列化函数。
序列化库的实现
序列化库的实现分为两部分:序列化和反序列化。在序列化过程中,我们需要将内存中的数据按照固定的JSON格式进行格式化输出,同时需要处理一些特殊的情况,例如NULL指针、空容器等。在反序列化过程中,则需要将JSON格式的字符串按照一定的规则解析出内存中的数据结构。
序列化
对于序列化,我们需要定义一个库级别的方法将各种类型的数据序列化成JSON字符串。
class json_serializer
{
public:
template<typename T>
static std::string serialize(T&& value) {
return serialize_impl(std::forward<T>(value));
}
private:
// 具体类型的序列化方法
template<typename T>
static std::string serialize_impl(const T& value);
};
在实现上,我们针对不同的类型定义了不同的序列化方法。例如,对于整型、浮点数等基本类型,我们可以直接将其转成字符串输出。对于数组和容器,我们需要迭代遍历并递归调用序列化方法。对于自定义类型,我们可以根据用户定义的编写自定义序列化函数。
以下是一个示例:
template<typename T>
typename std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T>, std::string>
json_serializer::serialize_impl(const T& value)
{
return std::to_string(value);
}
template<typename T>
typename std::enable_if_t<is_map_v<T>, std::string>
json_serializer::serialize_impl(const T& map)
{
std::string result = "{";
for (const auto& [key, value] : map) {
result += '"' + json_serializer::serialize(key) + '"' + ':' + json_serializer::serialize(value) + ',';
}
if (result.back() == ',') {
result.pop_back();
}
result += '}';
return result;
}
// 对于自定义类型,需要编写对应的序列化函数
struct person {
std::string name;
int age;
std::vector<std::string> hobbies;
};
std::string serialize(const person& p)
{
std::string result = "{";
result += "\"name\":" + json_serializer::serialize(p.name) + ",";
result += "\"age\":" + json_serializer::serialize(p.age) + ",";
result += "\"hobbies\":" + json_serializer::serialize(p.hobbies) + "}";
return result;
}
反序列化
在反序列化处理中,我们需要将JSON格式的字符串按照一定的规则解析出内存中的数据结构。在这里,我们可以借助于第三方库rapidjson
提供的解析器完成。
template<typename T>
typename std::enable_if_t<is_map_v<T>, T>
deserialize_impl(const rapidjson::Value& json)
{
std::map<typename T::key_type, typename T::mapped_type> result;
for (auto& m : json.GetObject()) {
result[deserialize<typename T::key_type>(m.name)] = deserialize<typename T::mapped_type>(m.value);
}
return result;
}
template<typename T>
typename std::enable_if_t<is_vector_v<T>, T>
deserialize_impl(const rapidjson::Value& json)
{
T result;
result.reserve(json.Size());
for (const auto& m : json.GetArray()) {
result.push_back(deserialize<typename T::value_type>(m));
}
return result;
}
// 对于自定义类型,需要编写对应的反序列化函数
struct person {
std::string name;
int age;
std::vector<std::string> hobbies;
};
void deserialize(const rapidjson::Value& json, person& p)
{
p.name = json["name"].GetString();
p.age = json["age"].GetInt();
p.hobbies = deserialize<std::vector<std::string>>(json["hobbies"]);
}
示例说明
以下是两条序列化的示例说明:
示例1
假设我们需要将以下的C++对象序列化成JSON字符串:
std::map<std::string, int> data1 = {{"apple", 1}, {"banana", 2}, {"pear", 3}};
std::vector<std::string> data2 = {"hello", "world"};
person data3 = {"Tom", 18, {"music", "basketball"}};
那么我们可以这样编写序列化代码:
std::string json = json_serializer::serialize(data1);
json += json_serializer::serialize(data2);
json += json_serializer::serialize(data3);
此时,json
的值为:
{"apple":1,"banana":2,"pear":3}["hello","world"]{"name":"Tom","age":18,"hobbies":["music","basketball"]}
示例2
假设我们需要将以下的JSON字符串反序列化成C++对象:
{"apple":1,"banana":2,"pear":3}
[["a","b"], ["c","d"]]
{"name":"Tom","age":18,"hobbies":["music","basketball"]}
那么我们可以这样编写反序列化代码:
std::map<std::string, int> data1;
std::vector<std::vector<std::string>> data2;
person data3;
rapidjson::Document doc;
doc.Parse(json);
data1 = deserialize<std::map<std::string, int>>(doc[0]);
data2 = deserialize<std::vector<std::vector<std::string>>>(doc[1]);
deserialize(doc[2], data3);
在以上的示例中,我们演示了如何将C++对象序列化成JSON字符串,并将JSON字符串反序列化为C++对象。可以看出,本序列化库具有高度的灵活性和可扩展性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ 轻量级对象JSON序列化实现详情 - Python技术站