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

如何访问TMDB JSON数据中的数组元素(基于nlohmann::json)

nlohmann::json解析TMDB数组字段返回空的解决方法

问题场景

从TMDB获取JSON数据并存储到本地后,使用nlohmann::json库解码时,string、boolean等基础类型处理正常,但处理genres这类数组字段时,调用array()方法返回空数组,无法读取内部元素。需要将genres数组中的name字段用;拼接,生成genres = Abenteuer;Action的INI格式内容。

相关代码与输出

遍历JSON根节点的代码:

using json = nlohmann::json;
{
  auto jsonData = json::parse(jsonText);
  // std::cout << jsonData.dump(1) << "\n";
  for (const auto &jsonItem : jsonData.items())
  {
    std::string jsonKey = jsonItem.key();
    std::string jsonValue = "";
    if (jsonItem.value().is_null()) { jsonValue = "(null)"; }
    else if (jsonItem.value().is_boolean()) { jsonValue = jsonItem.value() ? "(boolean) yes" : "(boolean) no"; }
    else if (jsonItem.value().is_string()) { jsonValue = "(string) '" + string_left(jsonItem.value(), 25) + "'"; }
    // ... 其他类型处理
    std::cout << jsonKey << ": " << jsonValue << "\n";
  }
}

屏幕输出片段:

adult: (boolean) no
belongs_to_collection: (null)
budget: (unsigned) 45000000
credits: (object)
genres: (array) [ . . . ]

原处理genres数组的代码及输出:

else if (jsonItem.key() == "genres") // array
{
  std::cout << "  jsonItem:       " << jsonItem << "\n"; // {"genres":[{"id":12,"name":"Abenteuer"},{"id":28,"name":"Action"}]}
  jsonKey = jsonItem.key();
  std::cout << "  jsonKey:        " << jsonKey << "\n"; // genres
  auto jsonValueArray = jsonItem.value().array();
  std::cout << "  jsonValueArray: " << jsonValueArray << " (" << sizeof(jsonValueArray) << ")\n"; // [] (16)
  auto jsonValueFlat = jsonItem.value().flatten();
  std::cout << "  jsonValueFlat:  " << jsonValueFlat << "\n"; // {"/0/id":12,"/0/name":"Abenteuer","/1/id":28,"/1/name":"Action"}
  std::cout << "  " << jsonKey << " elements: " << jsonValueArray.size() << "\n"; // 0
  // ... 遍历逻辑无输出
}

输出结果:

jsonItem:       {"genres":[{"id":12,"name":"Abenteuer"},{"id":28,"name":"Action"}]} 
  jsonKey:        genres 
  jsonValueArray: [] (16) 
  jsonValueFlat:  {"/0/id":12,"/0/name":"Abenteuer","/1/id":28,"/1/name":"Action"} 
  genres elements: 0

解决方案

问题根源在于array()方法返回的是数组视图(nlohmann::json::array_t),直接赋值可能导致视图失效。正确的做法是直接遍历数组类型的json对象本身,无需调用array()。

正确的数组处理代码

方式1:拼接成单个INI字段(符合需求)

else if (jsonItem.key() == "genres")
{
    std::vector<std::string> genreNames;
    // 直接遍历数组类型的json值
    for (const auto& genreObj : jsonItem.value())
    {
        // 安全检查字段是否存在
        if (genreObj.contains("name"))
        {
            genreNames.push_back(genreObj["name"].get<std::string>());
        }
    }

    // 用;拼接所有分类名称
    std::string joinedGenres;
    for (size_t i = 0; i < genreNames.size(); ++i)
    {
        if (i != 0)
        {
            joinedGenres += ";";
        }
        joinedGenres += genreNames[i];
    }

    // 写入INI格式内容
    iniText.append(jsonItem.key());
    iniText.append(" = ");
    iniText.append(joinedGenres);
    iniText.append("\n");

    // 调试输出
    std::cout << "  拼接结果: " << joinedGenres << "\n";
}

方式2:生成单个GenreX条目(可选)

如果需要生成Genre0 = Abenteuer、Genre1 = Action这类条目,可修改遍历逻辑:

else if (jsonItem.key() == "genres")
{
    size_t index = 0;
    for (const auto& genreObj : jsonItem.value())
    {
        if (genreObj.contains("name"))
        {
            std::string iniKey = "Genre" + std::to_string(index);
            std::string iniValue = genreObj["name"].get<std::string>();
            iniText.append(iniKey);
            iniText.append(" = ");
            iniText.append(iniValue);
            iniText.append("\n");
            index++;
        }
    }
}

核心说明

  1. 直接遍历json对象:数组类型的nlohmann::json实例支持范围for循环遍历,无需额外转换为数组视图。
  2. 安全字段访问:使用contains()检查字段是否存在,避免因JSON结构变化导致的异常。
  3. 类型转换:通过get<std::string>()将json字符串值转换为C++标准字符串,确保类型安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 05:05:40