c++11:nlohmann::json advanced basic_json template class

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.

In my last blog, I solved the problem of serialization and deserialization of third-party data types

Advanced use of c++11:nlohmann::json (II) using adl_serializer to solve the serialization and deserialization of third-party data types (such as uri)

The following is the implementation code to solve the problem:

namespace nlohmann {
	template <>
	struct adl_serializer<uri> {
		static uri from_json(const json& j) {
			
			return{ j.template get<std::string>() };
		}
		static void to_json(json& j, const uri &u) {			
			j = u.to_string();
		}
	};
}

Obviously, the ADL above_ Serializer < uri > class is only applicable to the conversion between nlohmann::json class and uri class. If nlohmann::json and nlohmann:: ordered are used in your project_ JSON needs to serialize and deserialize URIs. The above class is for nlohmann::ordered_json won't work. The simple way is to write another ADL with the above_ Serializer < uri > similar classes to implement nlohmann:: ordered_ Conversion between JSON and uri Can you write an ADL_ What about the serializer < URI > class?

basic_json

Then you need basic_json template class The nlohmann::json we usually use is actually the template class nlohmann::basic_json special case implementation. nlohmann::ordered_json, too. To solve the above problem, you need to use nlohmann::basic_json replaces nlohmann::son as the json object parameter type. Just change the nlohmann::json type parameter to nlohmann::basic_json, to_json,from_json can be changed to template functions to implement the nlohmann::json and nlohmann:: ordered_ JSON support As follows:

namespace nlohmann {
	template <>
	struct adl_serializer<uri> {
		// Template function with only one parameter, which is used to define the map type
		template<template<typename, typename, typename...> class ObjectType>
		static uri from_json(const basic_json<ObjectType>& j) {
			return{ j.template get<std::string>() };
		}
		template<template<typename, typename, typename...> class ObjectType>
		static void to_json(basic_json<ObjectType>& j, const uri &u) {
			j = u.to_string();
		}
	};
}

The above method only solves the basic problem_ The first template parameter ObjectType of JSON template class is variable. If you want to implement basic_ Full support for JSON template classes, to_json,from_json template parameters need to define basic_ All template parameters of JSON Refer to the macro definition in json.hpp, which is implemented as follows: nlohmann_json_test4.cpp

#include <iostream>
#include "uri/uri.hh"
#include "nlohmann/json.hpp"

#ifndef _BASIC_JSON_TPL_PARAMS_

#define _BASIC_JSON_TPL_PARAMS_                                 \
    ObjectType, ArrayType, StringType, BooleanType,             \
    NumberIntegerType, NumberUnsignedType, NumberFloatType,     \
    AllocatorType, JSONSerializer, BinaryType

#endif // !_BASIC_JSON_TPL_PARAMS_

#ifndef _BASIC_JSON_TPL_PARAM_DECL_

#define _BASIC_JSON_TPL_PARAM_DECL_                                                     \
	template<typename U, typename V, typename... Args> class ObjectType = std::map,        \
	template<typename U, typename... Args> class ArrayType = std::vector,                  \
	class StringType = std::string, class BooleanType = bool,                              \
	class NumberIntegerType = std::int64_t,                                                \
	class NumberUnsignedType = std::uint64_t,                                              \
	class NumberFloatType = double,                                                        \
	template<typename U> class AllocatorType = std::allocator,                             \
	template<typename T, typename SFINAE = void> class JSONSerializer = nlohmann::adl_serializer,    \
	class BinaryType = std::vector<std::uint8_t>

#endif // !_BASIC_JSON_TPL_PARAM_DECL_


#ifndef _BASIC_JSON_TPL_DECLARATION_
#define _BASIC_JSON_TPL_DECLARATION_ template<_BASIC_JSON_TPL_PARAM_DECL_>
#endif // !_BASIC_JSON_TPL_DECLARATION_

#ifndef  _BASIC_JSON_TPL_
#define _BASIC_JSON_TPL_                                           \
    nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType,   \
    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
    AllocatorType, JSONSerializer, BinaryType>

#endif // ! _BASIC_JSON_TPL_

namespace nlohmann {
	template <>
	struct adl_serializer<uri> {
		// Support basic_json all template parameters can be defined
		_BASIC_JSON_TPL_DECLARATION_
		static uri from_json(const _BASIC_JSON_TPL_& j) {
			return{ j.template get<std::string>() };
		}
		_BASIC_JSON_TPL_DECLARATION_
		static void to_json(_BASIC_JSON_TPL_& j, const uri &u) {
			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;
}

The above code has passed the compilation test under Visual Studio 2015

Posted on Mon, 29 Nov 2021 04:24:03 -0500 by lostboy