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

如何用boost::property_tree将std::unordered_map转为JSON数组?

问题:将std::unordered_map转换为指定JSON数组格式

给定如下C++ std::unordered_map数据:

std::unordered_map<std::string, std::vector<std::string>> data = {
    {"name", {"a", "b", "c", "d", "e"}},
    {"price", {"1.1", "2.2", "3.3", "4.4", "5.5"}},
    {"id", {"1", "2", "3", "4", "5"}}
};

需要转换为如下结构的JSON数组:

[
{
"id": "1",
"price": "1.1",
"name": "a"
},
{
"id": "2",
"price": "2.2",
"name": "b"
},
{
"id": "3",
"price": "3.3",
"name": "c"
},
{
"id": "4",
"price": "4.4",
"name": "d"
},
{
"id": "5",
"price": "5.5",
"name": "e"
}
]

尝试使用boost::property_tree::ptree和write_json函数实现,代码如下:

size_t nrows = 5;

boost::property_tree::ptree pt;

for(size_t i = 0; i < nrows; i++) {
    boost::property_tree::ptree body_node;
    for(const auto& kv : data) {
        body_node.put(kv.first, kv.second[i]);
    }
    pt.push_back(std::make_pair("", body_node));
}

boost::property_tree::write_json(std::cout, pt);

但得到的输出是带空键的JSON对象,而非预期数组:

{
"": {
"id": "1",
"price": "1.1",
"name": "a"
},
"": {
"id": "2",
"price": "2.2",
"name": "b"
},
"": {
"id": "3",
"price": "3.3",
"name": "c"
},
"": {
"id": "4",
"price": "4.4",
"name": "d"
},
"": {
"id": "5",
"price": "5.5",
"name": "e"
}
}

解决方案

原因分析

boost::property_tree::ptree的JSON实现存在局限性:它默认将根节点的空键子节点渲染为JSON对象的属性,而JSON对象不允许重复键,因此会出现上述错误输出。同时,ptree原生不支持直接输出顶层JSON数组,因为其根节点被设计为对象结构。

方案1:使用Boost.JSON库(推荐)

如果你的Boost版本≥1.75.0,建议使用Boost.JSON库,它原生支持JSON数组和对象,更贴合需求,代码更简洁:

#include <boost/json.hpp>
#include <iostream>
#include <unordered_map>
#include <vector>

namespace json = boost::json;

int main() {
    std::unordered_map<std::string, std::vector<std::string>> data = {
        {"name", {"a", "b", "c", "d", "e"}},
        {"price", {"1.1", "2.2", "3.3", "4.4", "5.5"}},
        {"id", {"1", "2", "3", "4", "5"}}
    };

    json::array arr;
    const size_t nrows = data.begin()->second.size();

    for (size_t i = 0; i < nrows; ++i) {
        json::object obj;
        for (const auto& kv : data) {
            obj[kv.first] = kv.second[i];
        }
        arr.push_back(obj);
    }

    std::cout << json::serialize(arr) << std::endl;
    return 0;
}

这段代码会直接输出符合预期的顶层JSON数组。

方案2:基于Boost.PropertyTree的兼容处理

如果必须使用property_tree,可以通过手动处理输出的方式绕过顶层数组的限制:

  1. 先将数组放在一个临时键的子节点中
  2. 输出后手动去除外层的对象包裹

修改后的代码:

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
#include <unordered_map>
#include <vector>
#include <sstream>

namespace pt = boost::property_tree;

int main() {
    std::unordered_map<std::string, std::vector<std::string>> data = {
        {"name", {"a", "b", "c", "d", "e"}},
        {"price", {"1.1", "2.2", "3.3", "4.4", "5.5"}},
        {"id", {"1", "2", "3", "4", "5"}}
    };

    const size_t nrows = 5;
    pt::ptree root_pt;
    pt::ptree array_pt;

    for (size_t i = 0; i < nrows; ++i) {
        pt::ptree body_node;
        for (const auto& kv : data) {
            body_node.put(kv.first, kv.second[i]);
        }
        array_pt.push_back(std::make_pair("", body_node));
    }

    root_pt.add_child("temp", array_pt);

    // 将输出写入字符串流
    std::ostringstream oss;
    pt::write_json(oss, root_pt);

    // 手动去除外层的 {"temp": ...} 包裹
    std::string json_str = oss.str();
    size_t start = json_str.find('[');
    size_t end = json_str.rfind(']');
    if (start != std::string::npos && end != std::string::npos) {
        std::cout << json_str.substr(start, end - start + 1) << std::endl;
    }

    return 0;
}

此方法通过字符串截取得到纯净的JSON数组输出,适合无法升级Boost版本的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:34:59