学习材料:nlohmann json
json官方
源码解析
源码
要学习并理解这份代码,可以按照以下步骤进行,逐步梳理代码的逻辑:
基本步骤:
-
配置宏:
- 理解用于配置的宏定义,这些宏控制库的不同特性和行为。
- 例如,
#if JSON_DIAGNOSTICS
用于控制诊断特性的启用。
-
核心类
basic_json
:- 分析
basic_json
类,它是整个库的核心,表示一个 JSON 值。 - 理解类中的成员变量(如
value_t
枚举和json_value
联合体)和它们的作用。 - 阅读并理解类的构造函数、析构函数、拷贝和移动构造函数及赋值运算符。
- 学习类中的成员函数,例如
operator[]
、get
、set
、is
等。
- 分析
-
序列化和反序列化:
- 理解用于将 JSON 值转换为字符串和从字符串转换回 JSON 值的序列化和反序列化逻辑。
- 例如,
json_serializer
类中的serialize
和deserialize
方法。
-
异常处理:
- 了解用于处理错误的自定义异常类,例如
json_exception
。 - 理解这些异常类如何与标准的异常处理机制集成,并提供有用的错误信息。
- 了解用于处理错误的自定义异常类,例如
basic_json
The basic_json
class is the core of the library, encapsulating all JSON types. Its design includes:
Type Management: An internal enum to manage the type of the JSON value.
Storage: A union to store different types efficiently.
Constructors and Destructors: To handle different JSON types.
Operators: Overloaded operators for ease of use.
// basic_json 类用于表示一个 JSON 值
template<typename BasicJsonType>
class basic_json
{
private:json_value m_value; // 存储 JSON 值的联合体value_t m_type = value_t::null; // 当前 JSON 值的类型public:// 构造函数basic_json() noexcept;basic_json(value_t t) noexcept;// 析构函数~basic_json() noexcept;// 拷贝和移动构造函数及赋值运算符basic_json(const basic_json& other);basic_json(basic_json&& other) noexcept;basic_json& operator=(const basic_json& other);basic_json& operator=(basic_json&& other) noexcept;// 成员函数// 示例:重载运算符 []reference operator[](size_type idx){// 检查类型并返回数组元素if (JSON_UNLIKELY(!is_array())){throw type_error::create(305, "cannot use operator[] with " + std::string(type_name()));}return m_value.array->operator[](idx);}
};
类型管理
JSON type | value_t type | used type |
---|---|---|
object | object | pointer to @ref object_t |
array | array | pointer to @ref array_t |
string | string | pointer to @ref string_t |
boolean | boolean | @ref boolean_t |
number | number_integer | @ref number_integer_t |
number | number_unsigned | @ref number_unsigned_t |
number | number_float | @ref number_float_t |
binary | binary | pointer to @ref binary_t |
null | null | no value is stored |
定义一个枚举来表示 JSON 值的类型
enum class value_t : std::uint8_t
{null, ///< null valueobject, ///< object (unordered set of name/value pairs)array, ///< array (ordered collection of values)string, ///< string valueboolean, ///< boolean valuenumber_integer, ///< number value (signed integer)number_unsigned, ///< number value (unsigned integer)number_float, ///< number value (floating-point)binary, ///< binary array (ordered collection of bytes)discarded ///< discarded by the parser callback function
};
C++11枚举类——enum class
联合体用于高效存储不同类型的 JSON 值
using string_t = StringType;using boolean_t = BooleanType;using number_integer_t = NumberIntegerType;using number_unsigned_t = NumberUnsignedType;using number_float_t = NumberFloatType;using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;using object_comparator_t = detail::actual_object_comparator_t<basic_json>;union json_value
{std::nullptr_t null;object_t* object;array_t* array;string_t* string;boolean_t boolean;number_integer_t number_integer;number_unsigned_t number_unsigned;number_float_t number_float;binary_t* binary;//构造函数json_value() = default;json_value(boolean_t v) noexcept : boolean(v) {}json_value(number_integer_t v) noexcept : number_integer(v) {}json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}json_value(number_float_t v) noexcept : number_float(v) {}json_value(value_t t){switch (t){case value_t::object:{object = create<object_t>();break;}case value_t::array:{array = create<array_t>();break;}case value_t::string:{string = create<string_t>("");break;}
.......}// 联合体的构造函数json_value() noexcept : null(nullptr) {}
};
Explanation of the Code
The code snippet you provided is a part of the nlohmann/json library’s template declarations and type definitions. Let’s break it down step-by-step.
1. number_integer_t
using number_integer_t = NumberIntegerType;
This line is a type alias declaration in C++. It creates an alias number_integer_t
for NumberIntegerType
. Essentially, wherever number_integer_t
is used, it refers to NumberIntegerType
.
2. Template Declaration Macro
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \template<template<typename, typename, typename...> class ObjectType, \template<typename, typename...> class ArrayType, \class StringType, class BooleanType, class NumberIntegerType, \class NumberUnsignedType, class NumberFloatType, \template<typename> class AllocatorType, \template<typename, typename = void> class JSONSerializer, \class BinaryType, \class CustomBaseClass>
This macro defines a template declaration for the basic_json
class template. It simplifies the repeated use of this long template parameter list by allowing the declaration to be inserted with a macro.
3. NumberIntegerType
Definition
class NumberIntegerType = std::int64_t;
This line defines NumberIntegerType
as a class that is actually an alias for std::int64_t
. This indicates that the default type for representing integer numbers in JSON is std::int64_t
, a 64-bit signed integer.
Reasons for This Design
a. Template Flexibility
The use of template parameters for various types (like NumberIntegerType
) allows the basic_json
class to be highly flexible. Users of the library can customize the JSON value types according to their needs. For instance, they can choose different types for integers, floats, strings, etc., based on specific requirements like memory constraints or performance needs.
b. Type Aliases for Readability
The using
alias (using number_integer_t = NumberIntegerType
) improves code readability and maintainability. It allows the library to use meaningful names throughout the implementation, making it clear what type each alias represents.
c. Macros for Simplification
The macro NLOHMANN_BASIC_JSON_TPL_DECLARATION
is used to simplify the repeated declaration of the template parameter list. This avoids redundancy and potential errors from copying the long template parameter list multiple times in the code.
Example Usage
Here’s a simplified example of how these templates and type aliases might be used in the basic_json
class:
NLOHMANN_BASIC_JSON_TPL_DECLARATION
class basic_json
{
public:using integer_t = NumberIntegerType; // Using the template parameter typeusing unsigned_t = NumberUnsignedType;using float_t = NumberFloatType;// Example function using the type aliasesvoid set_number(integer_t value){m_value.number_integer = value;m_type = value_t::number_integer;}private:union json_value{integer_t number_integer;unsigned_t number_unsigned;float_t number_float;// Other types...} m_value;value_t m_type = value_t::null;
};
In this example:
- The
basic_json
class template is declared using the macroNLOHMANN_BASIC_JSON_TPL_DECLARATION
. - The type aliases
integer_t
,unsigned_t
, andfloat_t
are used within the class to refer to the respective types specified by the template parameters. - A member function
set_number
demonstrates how the type aliasinteger_t
is used to define function parameters and manipulate the union membernumber_integer
.
Summary
This design approach provides flexibility, readability, and maintainability. It allows the basic_json
class to be easily customized for different types while keeping the code clean and understandable. The use of type aliases and macros ensures that the code remains concise and reduces the risk of errors from repetitive code.
成员变量
private:// Member variablesjson_value m_value; // Stores the actual datavalue_t m_type; // Represents the type of the stored data
构造函数
https://json.nlohmann.me/api/basic_json/basic_json/
一共有9个构造函数
json_serializer
// json_serializer 类用于 JSON 值的序列化和反序列化
template<typename BasicJsonType>
class json_serializer
{
public:static void serialize(const BasicJsonType& j, string_t& s){// 序列化实现}static void deserialize(const string_t& s, BasicJsonType& j){// 反序列化实现}
};// json_exception 类用于处理 JSON 库中的异常
class json_exception : public std::exception
{
public:explicit json_exception(const std::string& msg) : m_msg(msg) {}const char* what() const noexcept override{return m_msg.c_str();}private:std::string m_msg;
};
代码
未完待续