一.序列化和反序列化理解

1.序列化和反序列化是数据处理中的两个重要概念,特别是在数据传输和存储时。结合 nlohmann::json 库,以下是对这两个概念的解释:

序列化

序列化是将对象转换为一种可以存储或传输的格式的过程。在 nlohmann::json 库中,序列化通常是将 C++ 对象转换为 JSON 格式的字符串。

2.反序列化

反序列化是将存储或传输的格式转换回对象的过程。在 nlohmann::json 库中,反序列化通常是将 JSON 格式的字符串转换回 C++ 对象。

 

二.参考的使用方式
1.序列化

#include <iostream>
#include <string>
#include “nlohmann/json.hpp”

 

struct Person {
    std::string name;
    int age;
};

 

// 定义序列化方法
void to_json(nlohmann::json& j, const Person& p) {
    j = nlohmann::json{{“name”, p.name}, {“age”, p.age}};
}

 

int main() {
    Person person = {“John Doe”, 30};
    nlohmann::json j = person; // 序列化
    std::cout << j.dump(4) << std::endl; // 输出 JSON 字符串
    return 0;
}
#include <iostream>
#include <string>
#include “nlohmann/json.hpp”

 

struct Person {
    std::string name;
    int age;
};

 

2.反序列化

// 定义反序列化方法
void from_json(const nlohmann::json& j, Person& p) {
    j.at(“name”).get_to(p.name);
    j.at(“age”).get_to(p.age);
}

 

int main() {
    std::string jsonString = R”({“name”: “John Doe”, “age”: 30})”;
    nlohmann::json j = nlohmann::json::parse(jsonString);
    Person person = j.get<Person>(); // 反序列化
    std::cout << “Name: ” << person.name << “, Age: ” << person.age << std::endl;
    return 0;
}

三.Demo构建
(一)参考位置信息:

要在你的项目中使用 nlohmann::json 库,你需要引入 json.hpp 头文件。以下是如何引入和使用该库的步骤:

  1. 下载 json.hpp 文件: 你可以从 nlohmann/json GitHub 仓库 下载最新版本的 json.hpp 文件。你可以直接下载整个仓库的压缩包,或者只下载 single_include/nlohmann/json.hpp 文件。
  2. 将 json.hpp 文件添加到你的项目中: 将下载的 json.hpp 文件放到你的项目目录中,例如放在 include 文件夹中。

在你的代码中包含 json.hpp 文件: 在需要使用 JSON 功能的源文件中包含 json.hpp 头文件。

(二)具体实现demo

#include <iostream>
#include <vector>
#include <string>
#include "json.hpp" // 根据你的项目结构调整路径

struct FacebookConnectInsData_t {
    struct FacebookConnectInsInfo_t {
        std::string id;
        std::string name;
        std::string access_token;
        struct FacebookConnectInsAccountId_t {
            std::string id;
        };
        FacebookConnectInsAccountId_t instagram_business_account;
    };
    std::vector<FacebookConnectInsInfo_t> data;
};

// 使用自定义宏定义序列化和反序列化方法
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(FacebookConnectInsData_t::FacebookConnectInsInfo_t::FacebookConnectInsAccountId_t, id)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(FacebookConnectInsData_t::FacebookConnectInsInfo_t, id, name, access_token, instagram_business_account)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(FacebookConnectInsData_t, data)

//// 定义序列化方法
//void to_json(nlohmann::json& j, const FacebookConnectInsData_t::FacebookConnectInsInfo_t::FacebookConnectInsAccountId_t& p) {
//    j = nlohmann::json{{"id", p.id}};
//}
//
//void to_json(nlohmann::json& j, const FacebookConnectInsData_t::FacebookConnectInsInfo_t& p) {
//    j = nlohmann::json{
//            {"id", p.id},
//            {"name", p.name},
//            {"access_token", p.access_token},
//            {"instagram_business_account", p.instagram_business_account}
//    };
//}
//
//void to_json(nlohmann::json& j, const FacebookConnectInsData_t& p) {
//    j = nlohmann::json{{"data", p.data}};
//}
//
//// 定义反序列化方法
//void from_json(const nlohmann::json& j, FacebookConnectInsData_t::FacebookConnectInsInfo_t::FacebookConnectInsAccountId_t& p) {
//    j.at("id").get_to(p.id);
//}
//
//void from_json(const nlohmann::json& j, FacebookConnectInsData_t::FacebookConnectInsInfo_t& p) {
//    j.at("id").get_to(p.id);
//    j.at("name").get_to(p.name);
//    j.at("access_token").get_to(p.access_token);
//    if (j.contains("instagram_business_account")) {
//        j.at("instagram_business_account").get_to(p.instagram_business_account);
//    } else {
//        p.instagram_business_account = FacebookConnectInsData_t::FacebookConnectInsInfo_t::FacebookConnectInsAccountId_t{};
//    }
//}
//
//void from_json(const nlohmann::json& j, FacebookConnectInsData_t& p) {
//    j.at("data").get_to(p.data);
//}

//// 自定义异常类
class JsonParseException : public std::exception {
public:
    explicit JsonParseException(const std::string& message) : msg_(message) {}
    virtual const char* what() const noexcept override {
        return msg_.c_str();
    }
private:
    std::string msg_;
};

// 宏定义,用于抛出异常并附加位置信息
#define THROW_EXCEPTION_WITH_LOCATION(ex) \
    throw ex

int main() {
    std::string jsonString = R"({
        "data":[
            {
                "id":"489780270890201",
                "name":"Fxtest3",
                "access_token":"EAAG7WZAgNVLQBO7j88UJO0ag4tAErVoFhGeRCUGimx8IjClDr2Lc1Cb5cZCVZBtJSvb8bm3vhZAbdeIYaxQyBzaUvjwigls4l7gOB0PwDilBGk6xQRbdtHSuKL6GrOzb304V3ZA96n2BVpTgzNO77tDsXITYD6zJq8WDWY5X2b9JtSGunHwZAMECtOTPYh2BOklXrBA2Nuf4AJSNb2253EsJWt",
                "instagram_business_account":{"id":"17841466430598351"}
            },
            {
                "id":"443174595541934",
                "name":"\u516c\u5171\u4e3b\u9875\u4e8c-test",
                "access_token":"EAAG7WZAgNVLQBO9t8gzA6QkKXv9l9AfrjRTTiMTGGpPOgxQTZAN8eN0tHOkU1v0y2naLryxnOu7fdOGIQnOE7ymOs7MN8CkmtlX9V2XIZAZC9fT2Qzs9QgSSnxZBQDsxoFoAd1kG92ErwKMtZBOVb6f3vAQ7RUOOsICacxyGOhD8g0WntNvu0ZCBVFn8AO1olnZCX9l4vevZBM59INVKWvztWqME6"
            },
            {
                "id":"408818272321246",
                "name":"\u516c\u5171\u4e3b\u9875\u4e00",
                "access_token":"EAAG7WZAgNVLQBOzK0ONtR1JKJvYZBqchURZCSucBkESmZBLy5ZCMhDrHJouS2eMQWZB6ihkv8ZApejNfa6MtOX2cXrhaPxq4Skp0ggbZCRRoM9mZAAvwl3lQ2LM3API8fKcwGZB27ZCEz7fkyTzMVgBJztUrK2suNDHH0tT646rZA4hOwRpf8WSViV3enzAOsrOGgjLGOywfnNp4wQQ0ZBITaagfjONGi",
                "instagram_business_account":{"id":"17841469640446032"}
            },
            {
                "id":"442463848945616",
                "name":"FastFish",
                "access_token":"EAAG7WZAgNVLQBO6E3NUDSuthdRO79gxgNjwCAvGqmDYPBucBwSsYPJzMauygDLwzaRSmbZCx7NlAQLzAKUKFQdXyfqS6NSpVh66SuEuOVEu2Ys1zZANGu5glGMLAsrTPz6Ta12RoH9mJI4VqLVjUgj6v0J3rCpSPwFrlaSQ412zC2Hihx8HZA2RZBBdFbMlaG9zW1iwhjZC2bN5ErVELyz2GZBb"
            }
        ],
        "paging":{
            "cursors":{
                "before":"QVFIUmVnWldwSDludGZA6RVM4OVZAGTXZAydkNNdU9SMGlYWTVKQXhVb0RkYnBUTlFlMjRzVjlBNGg0SVRHLWV0QTAwcV90Sno5S01NbHJjZAkI3dWdnTmlKekR3",
                "after":"QVFIUk5paktDWUNpX2pLUjNaMS04SmpoM3dod0ZA1WGJVSHgyQ2tPVWxFYnNEVzNPYU5FLTRReUZAGaHFSaUZAqTTJEM1FYUVQwSGVfY1FUdmpqOVZAyNkkyckt3"
            }
        }
    })";

    try {
        auto json = nlohmann::json::parse(jsonString);
        FacebookConnectInsData_t object = json.get<FacebookConnectInsData_t>();
        std::cout << "JSON parsed and converted successfully!" << std::endl;
        for (const auto& info : object.data) {
            std::cout << "ID: " << info.id << std::endl;
            std::cout << "Name: " << info.name << std::endl;
            std::cout << "Access Token: " << info.access_token << std::endl;
            std::cout << "Instagram Business Account ID: " << info.instagram_business_account.id << std::endl;
        }
    } catch (nlohmann::json::parse_error& e) {
        JsonParseException ex(e.what());
        THROW_EXCEPTION_WITH_LOCATION(ex);
    } catch (nlohmann::json::type_error& e) {
        JsonParseException ex(e.what());
        THROW_EXCEPTION_WITH_LOCATION(ex);
    } catch (std::exception& e) {
        THROW_EXCEPTION_WITH_LOCATION(JsonParseException(e.what()));
    }

    return 0;
}

四.结合异常函数检测序列化情况;
1.异常检测函数:
#ifndef BSNET_HTTPCLIENTEXCEPTIONS_H_
#define BSNET_HTTPCLIENTEXCEPTIONS_H_
#include <exception>
#include <string>
#include <numeric>
/*
* @brief: exceptions for httpclient module
*/
namespace httpclient {
class BaseException : public std::exception
{
public:
    BaseException() = default;
BaseException(const std::exception& e) : std::exception(e) {}
#ifdef WIN32
    BaseException(const std::string& msg) : std::exception(msg.c_str()) {}
#else
    BaseException(const std::string& msg) : std::exception() {}
#endif
    virtual void raise() const { throw *this; }
    virtual BaseException* clone() const
    {
        return new BaseException{*this};
    }
    std::string where() const { return m_where; }
    void setWhere(const std::string& w) { m_where = w;}
private:
    std::string m_where;
};
class JsonParseException : public BaseException
{
public:
    JsonParseException(const std::string& msg) : BaseException(msg) {}
    void raise() const override { throw *this; }
    JsonParseException* clone() const override
    {
        return new JsonParseException{*this};
    }
};
class ConvertTypeException : public BaseException
{
public:
    ConvertTypeException(const std::string& msg) : BaseException(msg) {}
    void raise() const override { throw *this; }
    ConvertTypeException* clone() const override
    {
        return new ConvertTypeException{*this};
    }
};
class EmptyResponseException : public BaseException
{
public:
    EmptyResponseException(const std::string& msg) : BaseException(msg) {}
    void raise() const override { throw *this; }
    EmptyResponseException* clone() const override
    {
        return new EmptyResponseException{ *this };
    }
};
template<class ExceptionType>
static inline ExceptionType buildExceptionLocation(ExceptionType exception,
                                                   int fileLine,
                                                   const std::string& fileName,
                                                   const std::string& funcName)
{
    std::vector<std::string> elements;
elements.reserve(3);
    elements = { std::to_string(fileLine), fileName, funcName };
    std::string result;
    result = std::accumulate(elements.begin(), elements.end(), result, [](const std::string& lhs, const std::string& rhs) {
return lhs.empty() ? rhs : lhs + “:” + rhs;
    });
    exception.setWhere(result);
    return std::move(exception);
}
}  // namespace httpclient
#define THROW_EXCEPTION_WITH_LOCATION(exception_object) throw httpclient::buildExceptionLocation(exception_object, __LINE__, __FILE__, __FUNCTION__);
#endif // BSNET_HTTPCLIENTEXCEPTIONS_H_
2.转换实现函数:(其中的头文件、异步调用文件可以不参考)
#include “networkaccessor.h”
#include “json.hpp”
#include “httpclientexceptions.h”
#include “httpclientreply.h”
namespace httpclient {
template<class T>
prm::Promise<T> NetworkAccessor::request(const HttpClientRequest & req) const
{
    static_assert(std::is_constructible_v<T>, “T is not default constructible.”);
    return access1(req).then([](std::string raw_body){
        raw_body = {};
        if (raw_body.empty()) {
            EmptyResponseException ex(“Empty response from server”);
            THROW_EXCEPTION_WITH_LOCATION(ex);
        }
        try {
            auto json = nlohmann::json::parse(raw_body);
            T object = json.get<T>();
            return object;
        } catch (nlohmann::json::parse_error& e) {
            JsonParseException ex(e.what());
            THROW_EXCEPTION_WITH_LOCATION(ex);
        } catch (nlohmann::json::type_error& e) {
            ConvertTypeException ex(e.what());
            THROW_EXCEPTION_WITH_LOCATION(ex);
        } catch (std::exception& e) {
THROW_EXCEPTION_WITH_LOCATION(BaseException(e));
        }
    });
}
} // namespace httpclient
五.注意细节:
  1. 缺乏默认键的情况 : 反序列化失败,存在没有默认的键是,需要使用默认的。 采用NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT宏而不是NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE。即可解决问题。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。