c++11:nlohmann::json advanced application adl_serializer solves the serialization and deserialization of third-party data types (such as URIs)

nlohmann::json The source code of nlohmann/json is written based on the C++11 standard. The whole source code is a file nlohmann/json.hpp, which is very convenient to reference. About the basic use of nlohmann/json official website( https://github.com/nlohmann/json )There is a more detailed introduction on. I won't repeat it here. This article mainly introduces some extension functions and important but not well understood features that I use nlohmann/json in addition to the basic use of nlohmann/json.

uri

ben-zen/uri-library It is a URI parsing tool written in C++11 that I found on the Internet. It is used to parse a URI string into a URI object. It only needs a header file uri.hh, which is very convenient for reference. In my project, I use URI instead of ordinary std::string to save a URI address, but I have trouble saving the URI object to nlohmann::json. Of course, I hope to simply save a uri object to nlohmann::json as follows

nlohmann_json_test3.cpp

#include <iostream>
#include "uri/uri.hh"
#include "nlohmann/json.hpp"
int main()
{
	nlohmann::json j ;
	uri u = "http://baidu.com";
	// Save to json
	j["uri"] = u;
	// Reading uri objects from json
	uri u2 = j["uri"].get<uri>();
	std::cout << "u2:" << u2.to_string() << std::endl;
}

In fact, it's impossible to write directly like this. Because uri is a third-party type and is not the basic data type supported by nlohmann::json, nlohmann::json doesn't know how to serialize and deserialize it, so an error will be reported during compilation.

If you know a little about nlohmann/json, according to the basic usage of the official website of nlohmann/json, developers need to implement the custom data types that nlohmann/json does not support_ JSON (basicjsontype & J, const T & value) and from_ JSON (const basicjsontype & J, T & value) function, nlohmann/json will know how to serialize and deserialize this type.

Then I'll do it myself_ JSON (basicjsontype & J, const URI & value) and from_ JSON (const basicjsontype & J, URI & value) is OK?

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>();
}

Hehe, it's also inappropriate, because when you carefully check the source code uri/uri.hh, you find that the URI object has no default constructor. If there is no default constructor, you cannot construct a default uri object, as shown above_ Where do the input parameters of JSON (basicjsontype & J, const uri & value) come from?

adl_serializer

Take a closer look at the official nlohmann/json document and find that people have also provided a corresponding solution for this third-party data type without default constructor and non user-defined type, that is, adl_serializer template class.

All we need to do is provide nlohmann:: ADL for the uri implementation_ Special case implementation of serializer template class: The above code is nlohmann_ json_ Add ADL in test3.cpp as follows_ Serializer < URI > can be compiled and run normally:

#include <iostream>
#include "uri/uri.hh"
#include "nlohmann/json.hpp"
namespace nlohmann {
	// There is no default constructor for uri. You should provide serialization and deserialization methods in the following way, otherwise JSON:: get < uri > () cannot be called
	template <>
	struct adl_serializer<uri> {
		static uri from_json(const json& j) {
			// Deserialization
			// Get std::string from json and call the constructor of uri
			// uri(std::string const &uri_text, scheme_category category = scheme_category::Hierarchical,
            // query_argument_separator separator = query_argument_separator::ampersand)
      		// Convert std::string to uri object
			return{ j.template get<std::string>() };
		}
		static void to_json(json& j, const uri &u) {
			// serialize
			// Call uri:: to_ The string () function converts the uri object to std::string and saves it to json
			j = u.to_string();
		}
	};
}

int main()
{
	nlohmann::json j ;
	uri u = "http://baidu.com";
	// Save to json
	j["uri"] = u;
	// Reading uri objects from json
	uri u2 = j["uri"].get<uri>();
	std::cout << "u2:" << u2.to_string() << std::endl;
}

Posted by mogster on Mon, 29 Nov 2021 05:23:23 -0800