关于nlohmann结构体(类)和JSON相互转换的四个宏

前言

上文介绍了结构体(类)与JSON相互转换的基本操作步骤——http://t.csdnimg.cn/VQNa0

同事也提到了四个宏分为两类——侵入式,非侵入式。

一:侵入式与非侵入式

侵入式

struct People
{
    std::string name;
    int age;
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(People, name, age)
    // NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(People, name, age)
};
  1. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT

  2. NLOHMANN_DEFINE_TYPE_INTRUSIVE

侵入式在结构体(类)内部使用,因为侵入式宏会在编译时给结构体(类)生成两个to_json()和from_json();下面是json.hpp中关于两个侵入式宏的定义

#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \
    friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
    friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }

#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
    friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
    friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }

非侵入式

struct People
{
    std::string name;
    int age; 
};
    NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(People, name, age)
  1. NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE

  2. NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT

非侵入式宏在结构体(类)外部使用,非侵入式宏会在编译时生成两个内敛函数to_json()和from_json();

#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)  \
    inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
    inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }

#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...)  \
    inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }

二:初始化值与不带初始化值 

  1. NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE

  2. NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT

  3. NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT

  4. NLOHMANN_DEFINE_TYPE_INTRUSIVE

又分为两类  是否带有初始值

带有初始值

  1.  NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
  2. NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
#include "iostream"
#include "myStruct.h"
#include "json.hpp"
using namespace std;

struct People
{
    std::string name = "asd";
    int age = 123;

    NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(People, name, age)
};
// NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(People, name, age)

int main(void)
{
    // string jsonStr = "{\"age\":24,\"name\":\"asd\"}";
    string jsonStr = "{\"age\":24}";
    nlohmann::json js = nlohmann::json::parse(jsonStr);
    People me = js.get();
    cout << "name::" << me.name << endl;
    cout << "age::" << me.age << endl;
    return 0;
}

带有初始值的宏能够在 反序列化(也就是json转换为结构体或者类)时,补全json字符串中缺少的成员值。例如上述代码中,解析的字符串中只有“age”,没有“name”。在执行get()时,会补充“name”键值对,值为结构体成员“name”的默认值 123;

上述代码执行结果:

name::asd
age::24

 不带初始值

#include "iostream"
#include "json.hpp"
using namespace std;

struct People
{
    std::string name;
    int age;

    NLOHMANN_DEFINE_TYPE_INTRUSIVE(People, name, age)
};
// NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(People, name, age)

int main(void)
{
    // string jsonStr = "{\"age\":24,\"name\":\"asd\"}";
    string jsonStr = "{\"age\":24}";
    nlohmann::json js = nlohmann::json::parse(jsonStr);
    People me = js.get();
    cout << "name::" << me.name << endl;
    cout << "age::" << me.age << endl;
    return 0;
}

该代码执行会报错

terminate called after throwing an instance of 'nlohmann::json_abi_v3_11_3::detail::out_of_range'
  what():  [json.exception.out_of_range.403] key 'name' not found

使用不带默认值的宏时,必须保证json字符串包含所有宏中使用的变量。

以上就是四个宏的区别。 

你可能感兴趣的:(nlohmann::json,结构体(类)与JSON相互转换,json)