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

使用cereal库解析JSON时触发rapidjson IsArray断言失败错误怎么办?

使用cereal解析JSON时出现IsArray()断言错误的解决办法

问题场景

编写小游戏代码时,用cereal库读取JSON作为玩家配置,简化后的示例代码运行报错,错误提示Error deserializing JSON: rapidjson internal assertion failure: IsArray()。

示例C++代码

#include <cereal/types/map.hpp>
#include <cereal/types/string.hpp>
#include <cereal/archives/json.hpp>
#include <string>
#include <map>
#include <iostream>
#include <fstream>


struct Item {
    std::string name;
    int number;

    template <class Archive>
    void serialize(Archive &ar) {
        ar(cereal::make_nvp("name", name), cereal::make_nvp("number", number));
    }
};

int main() {
    std::map<std::string, Item> items;


    std::ifstream file("dataForTesting.json");
    if (!file.is_open()) {
        std::cerr << "Could not open the file!" << std::endl;
        return 1;
    }

    try {
        cereal::JSONInputArchive archive(file);

        archive(items);

    } catch (const cereal::Exception& e) {
        std::cerr << "Error deserializing JSON: " << e.what() << std::endl;
        return 1;
    } catch (const std::exception& e) {
        std::cerr << "An error occurred: " << e.what() << std::endl;
        return 1;
    }


    for (const auto& item : items) {
        std::cout << "Item ID: " << item.first 
                  << "\nName: " << item.second.name 
                  << "\nNumber: " << item.second.number << "\n" << std::endl;
    }
    return 0;
}

对应的JSON文件(dataForTesting.json)

{
    "item1": {
        "name": "Item One",
        "number": 1
    },
    "item2": {
        "name": "Item Two",
        "number": 2
    },
    "item3": {
        "name": "Item Three",
        "number": 3
    }
}

编译与执行命令

c++ testingTesting.c++ -o test -std=c++11 -I.
./test

错误信息

Error deserializing JSON: rapidjson internal assertion failure: IsArray()

核心原因与解决办法

cereal默认要求std::map对应的JSON是数组形式的键值对集合,而不是直接的对象嵌套。以下三种方案任选其一即可解决:

方案1:修改JSON为数组结构

把原JSON改成数组格式,每个元素包含key和value字段:

[
    {
        "key": "item1",
        "value": {
            "name": "Item One",
            "number": 1
        }
    },
    {
        "key": "item2",
        "value": {
            "name": "Item Two",
            "number": 2
        }
    },
    {
        "key": "item3",
        "value": {
            "name": "Item Three",
            "number": 3
        }
    }
]

方案2:给map套一层结构体(无需修改JSON)

在代码中给std::map包装一个结构体,让cereal识别外层对象:

struct ItemMap {
    std::map<std::string, Item> items;

    template <class Archive>
    void serialize(Archive &ar) {
        ar(items);
    }
};

同时修改main函数中的逻辑:

int main() {
    ItemMap itemMap;

    std::ifstream file("dataForTesting.json");
    if (!file.is_open()) {
        std::cerr << "Could not open the file!" << std::endl;
        return 1;
    }

    try {
        cereal::JSONInputArchive archive(file);
        archive(itemMap);

        for (const auto& item : itemMap.items) {
            std::cout << "Item ID: " << item.first 
                      << "\nName: " << item.second.name 
                      << "\nNumber: " << item.second.number << "\n" << std::endl;
        }
    } catch (const cereal::Exception& e) {
        std::cerr << "Error deserializing JSON: " << e.what() << std::endl;
        return 1;
    } catch (const std::exception& e) {
        std::cerr << "An error occurred: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

方案3:给map指定顶层键名(需修改JSON)

修改JSON,把整个map放在一个顶层键下:

{
    "items": {
        "item1": {
            "name": "Item One",
            "number": 1
        },
        "item2": {
            "name": "Item Two",
            "number": 2
        },
        "item3": {
            "name": "Item Three",
            "number": 3
        }
    }
}

然后修改反序列化代码,用make_nvp指定键名:

archive(cereal::make_nvp("items", items));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 11:01:07