Bootstrap

【C++】数据上传的方式。持久化的方式。通过 JSON,序列化与反序列化。

在 C++/CLI 或 C++/CLR 项目中,数据上传通过 JSON 是一种常见的方式。它通常需要用到 序列化反序列化 处理数据,以便将数据转化为 JSON 格式(上传)或从 JSON 格式解析(下载)。

通过示例说明。


名词解释

1. 序列化(Serialization)

  • 定义
    • 序列化是将内存中的对象或数据结构转换为一种格式(如 JSON、XML、二进制等),以便数据可以存储到文件、传输到网络或与其他系统交换。
  • 作用
    • 将 C++ 对象(如类、结构体)转换为 JSON 格式的字符串。
  • 常见用途
    • 数据上传到服务器。
    • 数据持久化到文件。

2. 反序列化(Deserialization)

  • 定义
    • 反序列化是序列化的逆过程,它将存储的格式化数据(如 JSON 字符串)重新解析回内存中的对象或数据结构。
  • 作用
    • 将 JSON 数据(从文件或网络接收)解析为 C++ 对象。
  • 常见用途
    • 从服务器接收数据。
    • 读取存储的 JSON 文件,并将其转换为可操作的对象。

3. JSON(JavaScript Object Notation)

  • 定义

    • JSON 是一种轻量级的数据交换格式,易于人类阅读和机器解析。
    • JSON 使用键值对的形式存储数据,例如:
      {
        "name": "Alice",
        "age": 25,
        "isAdmin": true
      }
      
  • 特点

    • 平台无关:适用于不同的编程语言(如 C++、C#、Python 等)。
    • 易于解析:现代编程语言都提供了丰富的 JSON 库。

序列化与反序列化的应用

在 C++/CLI 或 C++/CLR 中,序列化和反序列化通常结合 JSON 库进行,以下实现:


1. 序列化:对象转为 JSON

示例场景:上传用户信息

将用户对象转换为 JSON 格式,上传到服务器。

示例代码:
#include <msclr/marshal_cppstd.h>
#include <nlohmann/json.hpp>
using namespace System;

// 定义一个用户对象
struct User {
    std::string name;
    int age;
    bool isAdmin;
};

// 序列化函数
std::string SerializeUser(const User& user) {
    nlohmann::json jsonObject;
    jsonObject["name"] = user.name;
    jsonObject["age"] = user.age;
    jsonObject["isAdmin"] = user.isAdmin;

    return jsonObject.dump();  //用于将 JSON 对象转换为 JSON 格式的字符串。
}

// 上传函数
void UploadUserData(User user) {
    std::string jsonData = SerializeUser(user);
    // 假设上传使用 C++/CLR 与托管代码交互
    String^ managedJsonData = gcnew String(jsonData.c_str());
    Console::WriteLine("Uploading JSON: " + managedJsonData);

    // 这里可以使用 WebClient 或其他网络库发送数据到服务器
}
调用示例:
User user = {"Alice", 25, true};
UploadUserData(user);
输出结果:
Uploading JSON: {"name":"Alice","age":25,"isAdmin":true}

2. 反序列化:JSON 转为对象

示例场景:从服务器接收用户数据

从服务器接收 JSON 数据,解析为 C++ 对象。

示例代码:
#include <nlohmann/json.hpp>

// 反序列化函数
User DeserializeUser(const std::string& jsonData) {
    nlohmann::json jsonObject = nlohmann::json::parse(jsonData);

    User user;
    user.name = jsonObject["name"].get<std::string>();
    user.age = jsonObject["age"].get<int>();
    user.isAdmin = jsonObject["isAdmin"].get<bool>();

    return user;
}

// 模拟接收数据
void ReceiveUserData(const std::string& jsonResponse) {
    User user = DeserializeUser(jsonResponse);
    std::cout << "User Name: " << user.name << "\n"
              << "User Age: " << user.age << "\n"
              << "Is Admin: " << (user.isAdmin ? "Yes" : "No") << std::endl;
}
调用示例:
std::string jsonResponse = R"({"name":"Bob","age":30,"isAdmin":false})";
ReceiveUserData(jsonResponse);
输出结果:
User Name: Bob
User Age: 30
Is Admin: No

3. 使用 C++/CLI 实现与托管代码的交互

如果你需要在 C++/CLI 中操作 JSON 数据(例如与 .NET 类库交互),可以通过 marshal_as 或其他工具桥接托管字符串和非托管 JSON 处理。

示例:
#include <msclr/marshal_cppstd.h>
#include <nlohmann/json.hpp>
using namespace System;

// 定义托管接口
public ref class JsonProcessor {
public:
    static String^ SerializeToJson(String^ name, int age, bool isAdmin) {
        // 转换托管到非托管字符串
        std::string nativeName = msclr::interop::marshal_as<std::string>(name);

        // 构建 JSON
        nlohmann::json jsonObject;
        jsonObject["name"] = nativeName;
        jsonObject["age"] = age;
        jsonObject["isAdmin"] = isAdmin;

        // 转换非托管字符串回托管字符串
        return gcnew String(jsonObject.dump().c_str());
    }

    static void DeserializeFromJson(String^ json) {
        // 转换托管到非托管字符串
        std::string nativeJson = msclr::interop::marshal_as<std::string>(json);

        // 解析 JSON
        nlohmann::json jsonObject = nlohmann::json::parse(nativeJson);

        // 提取数据
        std::string name = jsonObject["name"].get<std::string>();
        int age = jsonObject["age"].get<int>();
        bool isAdmin = jsonObject["isAdmin"].get<bool>();

        Console::WriteLine("Name: " + gcnew String(name.c_str()));
        Console::WriteLine("Age: " + age);
        Console::WriteLine("Is Admin: " + isAdmin);
    }
};
调用示例(在托管环境中):
String^ json = JsonProcessor::SerializeToJson("Charlie", 28, true);
Console::WriteLine("Serialized JSON: " + json);

JsonProcessor::DeserializeFromJson(json);
输出结果:
Serialized JSON: {"name":"Charlie","age":28,"isAdmin":true}
Name: Charlie
Age: 28
Is Admin: True

小结

  1. JSON 数据上传

    • 序列化:将对象转化为 JSON 格式用于传输。
    • 示例:将用户对象转换为 JSON 并上传到服务器。
  2. JSON 数据接收

    • 反序列化:从 JSON 格式解析为对象,用于操作。
    • 示例:从服务器接收 JSON,解析用户信息。
  3. C++/CLI 的作用

    • 作为桥梁连接托管和非托管代码,通过 marshal_as 或其他工具方便地实现托管与非托管字符串的转换。
    • 在 .NET 环境中,可以与 JSON 库(如 nlohmann/json 或 RapidJSON)结合使用,高效处理 JSON 数据。
;