c++11:nlohmann::json进阶使用(二)应用adl_serializer解决第三方数据类型(such as uri)的序列化和反序列化

nlohmann::json是非常好用的一个json开源解析库.nlohmann/json的源码是基于C++11标准写的,整个源码就是一个文件 nlohmann/json.hpp,引用非常方便。
关于nlohmann/json的基本使用官网(https://github.com/nlohmann/json)上有比较详细的介绍。这里不再赘述,本文主要是介绍在nlohmann/json的基本使用之外一些我在使用 nlohmann/json 用到的一些扩展功能和重要但不太被了解的特性。

uri

ben-zen/uri-library是我在网上找到的一个C++11写的URI解析工具,用于URI字符串解析为一个uri对象,只需要一个头文件uri.hh,引用非常方便。
在我的项目中我使用uri而不是普通的std::string来保存一个URI地址,但是在将uri对象保存到 nlohmann::json 时遇到了麻烦。
我当然希望如下就能简单的将一个uri对象保存到 nlohmann::json

nlohmann_json_test3.cpp

#include <iostream>
#include "uri/uri.hh"
#include "nlohmann/json.hpp"
int main()
{
    
    
	nlohmann::json j ;
	uri u = "http://baidu.com";
	// 保存到json
	j["uri"] = u;
	// 从json中读取uri对象
	uri u2 = j["uri"].get<uri>();
	std::cout << "u2:" << u2.to_string() << std::endl;
}

实际上直接这样写是不行的,因为uri是个第三方类型,并不是nlohmann::json支持的基本数据类型,所以nlohmann::json并不知道如何对它进行序列化和反序列化,所以编译就会报错。

如果你对nlohmann/json略有了解就知道,按照nlohmann/json官网的基本用法,对于nlohmann/json不支持的自定义数据类型开发者需要自己实现to_json(BasicJsonType& j, const T& value)from_json(const BasicJsonType& j, T& value)函数,nlohmann/json才会知道怎么对这个类型进行序列化和反序列化。

那么我自己实现to_json(BasicJsonType& j, const uri& value)from_json(const BasicJsonType& j, uri& value)不就可以了么?

void to_json(BasicJsonType& j, const uri& value)
{
    
    
	j = value.to_string();
}
void from_json(const BasicJsonType& j, uri& value)
{
    
    
	value = j.get<std::string>();
}

呵呵,也是不合适的,因为仔细查看源码uri/uri.hh源码,发现uri这个对象是没有默认构造函数的。
如果没有默认构造函数,也就无法有构造默认uri对象,上面to_json(BasicJsonType& j, const uri& value)的输入参数从何而来呢?

adl_serializer

再仔细看看nlohmann/json官方文档,发现人家对于这种没有默认构造函数,也非用户自定义类型的第三方数据类型也提供了相应解决方案,就是 adl_serializer模板类。
在这里插入图片描述
我们需要做的就是为uri实现提供 nlohmann::adl_serializer模板类的特例化实现:
上面代码nlohmann_json_test3.cpp中如下增加 adl_serializer<uri>就可以正常编译运行了:

#include <iostream>
#include "uri/uri.hh"
#include "nlohmann/json.hpp"
namespace nlohmann {
    
    
	// uri 没有默认构造函数,要采用下面的方式提供序列化和反序列化方法,否则json::get<uri>()不能调用
	template <>
	struct adl_serializer<uri> {
    
    
		static uri from_json(const json& j) {
    
    
			// 反序列化
			// 从json中获取std::string,调用uri的构造函数
			// uri(std::string const &uri_text, scheme_category category = scheme_category::Hierarchical,
            // query_argument_separator separator = query_argument_separator::ampersand)
      		// 将std::string转为uri对象
			return{
    
     j.template get<std::string>() };
		}
		static void to_json(json& j, const uri &u) {
    
    
			// 序列化
			// 调用 uri::to_string()函数将uri对象转为std::string保存到json
			j = u.to_string();
		}
	};
}

int main()
{
    
    
	nlohmann::json j ;
	uri u = "http://baidu.com";
	// 保存到json
	j["uri"] = u;
	// 从json中读取uri对象
	uri u2 = j["uri"].get<uri>();
	std::cout << "u2:" << u2.to_string() << std::endl;
}

猜你喜欢

转载自blog.csdn.net/10km/article/details/121557199