You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++标准库中是否存在与nlohmann json类似的灵活数据结构?

C++标准库中替代nlohmann json的灵活数据结构

C++标准库本身没有直接和nlohmann json完全对等、既支持动态键值对又自带序列化的结构,但可以通过组合现有容器实现类似能力,同时兼顾性能,以下是几种可行方案:

1. std::unordered_map + std::variant(C++17+)

这是最接近nlohmann json使用体验且性能较好的组合:用std::unordered_map存储键值对,std::variant作为值类型,支持容纳多种预定义类型。

#include <unordered_map>
#include <variant>
#include <string>
#include <functional>

using Value = std::variant<int, bool, std::string, std::unordered_map<std::string, Value>>;
using DynamicObject = std::unordered_map<std::string, Value>;

std::string character_new() {
    DynamicObject obj;
    obj["level"] = 1;
    obj["max_hp"] = 2;
    obj["hp"] = 2;

    DynamicObject skills;
    skills["atk"] = 1;
    skills["dex"] = 1;
    obj["skills"] = skills;

    obj["x"] = 1000;
    obj["y"] = 1000;
    obj["state"] = -1;
    obj["map"] = std::string("forest");
    obj["dead"] = false;
    obj["name"] = std::string("Some name");

    // 自定义序列化逻辑(递归遍历生成JSON格式)
    std::function<std::string(const Value&)> serialize = [&](const Value& val) -> std::string {
        if (std::holds_alternative<int>(val)) {
            return std::to_string(std::get<int>(val));
        } else if (std::holds_alternative<bool>(val)) {
            return std::get<bool>(val) ? "true" : "false";
        } else if (std::holds_alternative<std::string>(val)) {
            return "\"" + std::get<std::string>(val) + "\"";
        } else if (std::holds_alternative<DynamicObject>(val)) {
            const auto& map = std::get<DynamicObject>(val);
            std::string res = "{";
            bool first = true;
            for (const auto& [key, value] : map) {
                if (!first) res += ", ";
                res += "\"" + key + "\": " + serialize(value);
                first = false;
            }
            res += "}";
            return res;
        }
        return "";
    };

    return serialize(obj);
}
  • 优势:std::unordered_map的存取效率优于nlohmann json的底层结构,std::variant的类型擦除开销极小,整体性能更高。
  • 劣势:需要自行实现序列化/反序列化逻辑,访问值时需通过std::get或std::visit保证类型安全。

2. std::map + std::any(C++17+)

如果需要键有序的动态结构,可以用std::map替代std::unordered_map,搭配std::any实现完全无限制的类型存储:

#include <map>
#include <any>
#include <string>

using DynamicObject = std::map<std::string, std::any>;

std::string character_new() {
    DynamicObject obj;
    obj["level"] = 1;
    obj["max_hp"] = 2;
    // 其余字段赋值逻辑类似...
    
    // 序列化需自行实现,访问值时用std::any_cast,如:
    // int level = std::any_cast<int>(obj["level"]);
    return ""; // 替换为自定义序列化结果
}
  • 优势:能容纳任意类型,键天然有序。
  • 劣势:std::any的类型擦除开销比std::variant大,性能较差;类型转换时若类型不匹配会抛出异常,类型安全性弱。

3. 结构体 + 轻量序列化库(折中方案)

如果你的数据结构实际是固定的(比如示例中的角色属性),只是习惯了动态写法,更推荐用结构体配合轻量序列化库:

#include <string>
#include <unordered_map>

struct Character {
    int level = 1;
    int max_hp = 2;
    int hp = 2;
    std::unordered_map<std::string, int> skills{{"atk", 1}, {"dex", 1}};
    int x = 1000;
    int y = 1000;
    int state = -1;
    std::string map;
    bool dead = false;
    std::string name = "Some name";
};

// 用序列化库生成JSON或二进制格式(如flatbuffers、protobuf)
  • 优势:类型安全,性能远高于动态结构,序列化效率极高。
  • 劣势:无法在运行时动态添加新字段,结构需提前定义。

总结

  • 必须保留运行时动态添加键值对的灵活性:优先选std::unordered_map<std::string, std::variant<...>>,性能优于nlohmann json。
  • 可接受提前定义结构:用结构体+轻量序列化库,是性能最优的选择。
  • 非必要不要用std::any,它的性能和类型安全性都不如std::variant。

内容的提问来源于stack exchange,提问作者user19816087

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:27:27