Skip to content

Custom conversion (zh)

Nomango edited this page Jan 5, 2023 · 4 revisions

自定义类型绑定

configor 提供了 CONFIGOR_BIND 宏,可以用一行代码快速完成自定义类型绑定:

struct User
{
    int user_id;
    std::string user_name;

    CONFIGOR_BIND(
        json::value, User,     // 将 User 类绑定到 json
        REQUIRED(user_id),     // user_id 字段必填,空值会引发异常
        OPTIONAL(user_name)    // user_name 字段非必填,空值会被忽略
    );
};

对私有成员变量同样适用

class User
{
private:
    int user_id;
    std::string user_name;

public:
    // 绑定私有字段
    CONFIGOR_BIND(json::value, User, REQUIRED(user_id), OPTIONAL(user_name));
};

允许指定与 C++ 字段名不同的 JSON 字段名

class User
{
private:
    int user_id_;
    std::string user_name_;

public:
    // 为 JSON 指定不同的名称,使 User 可以接受如 {"id": 1, "name": "John"} 这样的 JSON 内容
    CONFIGOR_BIND(json::value, User, REQUIRED(user_id_, "id"), OPTIONAL(user_name_, "name"));
};

宽字符类型绑定

绑定宽字符类型的字段时,必须指定 L 开头的字段名

class User
{
private:
    int user_id;
    std::wstring user_name;

public:
    // 绑定到 wjson 类型,使用 L 开头的宽字符字段名
    CONFIGOR_BIND(wjson::value, User, REQUIRED(user_id, L"user_id"), OPTIONAL(user_name, L"user_name"));
};

为了方便,可以自定义一个转换宏,例如

#define WREQUIRED(field) REQUIRED(field, L ## #field)
#define WOPTIONAL(field) OPTIONAL(field, L ## #field)

class User
{
private:
    int user_id;
    std::wstring user_name;

public:
    // 绑定到 wjson 类型,使用 WREQUIRED 和 WOPTIONAL
    CONFIGOR_BIND(wjson::value, User, WREQUIRED(user_id), WOPTIONAL(user_name));
};

自定义类型转换

json::value j;
User user;

// 将 User 转换为 json
j = user;

// 将 json 转换为 User
user = (User)j;

同时会默认支持 User 的智能指针、std::vector<User>、std::map<std::string, User> 等类型的自动转换。

例如,下面的代码是正确的:

std::vector<std::shared_ptr<User>> user_list;
json::value j = user_list;  // 可以正确处理复合类型的转换

对于第三方库的类型,由于无法侵入式的在其内部声明 CONFIGOR_BIND,可以通过特化实现 value_binder 类,非侵入式的绑定到 JSON。

特化实现 value_binder 的例子:

// 用户类
struct User
{
    int user_id;
    std::string user_name;
};

// 与 json 绑定
namespace configor
{
template <>
struct value_binder<User>
{
    static void to_value(json& j, const User& v)
    {
        j = { { "user_id", v.user_id }, { "user_name", v.user_name } };
    }

    static void from_value(const json& j, User& v)
    {
        j["user_id"].get(v.user_id);
        j["user_name"].get(v.user_name);
    }
};
}

自定义类型与输入输出流交互

使用 json::wrap 函数可以让任意类型实现序列化与反序列化,并与输入输出流交互

std::stringstream s;

// 把 obj 序列化,并输入到 s 流中
s << json::wrap(obj);

// 从 s 流中读取,并把 obj 反序列化
s >> json::wrap(obj);

Overview

  • Quick start ( en | zh )
  • Examples ( en | zh )

Features

  • Value operation ( en | zh )
  • Serialization ( en | zh )
  • Custom conversion ( en | zh )
  • Encoding support ( en | zh )

Other

  • Q&A ( en | zh )
  • Advanced ( en | zh )
Clone this wiki locally