如何用RapidJson C++解析数组型JSON为对象列表(无需循环)
用RapidJSON解析数组开头的JSON为C++对象列表
没问题,我来帮你搞定这个RapidJSON解析数组的问题!虽然RapidJSON没有像NewtonSoft那样直接提供ToObjectList()或ToList()的现成方法,但我们可以自己封装一个简洁的模板函数,让调用体验和你想要的一样清爽,不用手动写重复的遍历代码。
步骤1:定义对应JSON结构的C++结构体
首先,我们需要创建一个和JSON字段一一对应的结构体,用来存储每个数组元素的数据:
#include <rapidjson/document.h> #include <vector> #include <string> #include <cstdio> // 与JSON字段匹配的结构体,字段名可以自定义,只要解析时对应正确即可 struct TradeData { double C; int CO; double H; double L; double O; int64_t T; // 注意数值范围,用int64_t避免溢出 int64_t TO; int V; };
步骤2:封装解析数组到对象列表的模板函数
这个模板函数会帮你处理遍历逻辑,对外只需要传入RapidJSON的数组对象和目标结构体类型,就能直接得到对象列表:
// 模板函数:将RapidJSON数组转换为C++对象列表,相当于你想要的ToList() template<typename T> std::vector<T> ParseJsonArrayToObjectList(const rapidjson::Value& array) { std::vector<T> result; // 先判断输入是否为数组类型 if (!array.IsArray()) { return result; } // 内部遍历数组元素,解析为结构体对象(调用时无需关心这部分逻辑) for (const auto& item : array.GetArray()) { T obj; // 逐个字段解析,确保字段类型与JSON中的类型匹配 obj.C = item["C"].GetDouble(); obj.CO = item["CO"].GetInt(); obj.H = item["H"].GetDouble(); obj.L = item["L"].GetDouble(); obj.O = item["O"].GetDouble(); obj.T = item["T"].GetInt64(); obj.TO = item["TO"].GetInt64(); obj.V = item["V"].GetInt(); result.push_back(obj); } return result; }
步骤3:调用示例,一步获取对象列表
现在你可以像调用现成的ToList()方法一样,轻松把JSON数组转换成C++对象列表:
int main() { // 你的原始JSON字符串 const std::string json_str = R"([{ "C": 28563.0, "CO": 0, "H": 28563.0, "L": 28545.0, "O": 28547.0, "T": 1562907600, "TO": 41315958, "V": 1447 }, { "C": 28499.0, "CO": 0, "H": 28564.0, "L": 28494.0, "O": 28563.0, "T": 1562911200, "TO": 371724821, "V": 13030 }, { "C": 28516.0, "CO": 0, "H": 28536.0, "L": 28481.0, "O": 28499.0, "T": 1562914800, "TO": 301700826, "V": 10582 }, { "C": 28539.0, "CO": 0, "H": 28545.0, "L": 28500.0, "O": 28517.0, "T": 1562918400, "TO": 150871685, "V": 5290 }])"; rapidjson::Document doc; // 解析JSON字符串 doc.Parse(json_str.c_str()); // 处理解析错误 if (doc.HasParseError()) { printf("JSON解析错误,错误码:%u\n", doc.GetParseError()); return 1; } // 一步得到对象列表,完全不用手动遍历! std::vector<TradeData> trade_list = ParseJsonArrayToObjectList<TradeData>(doc); // 验证解析结果,比如打印第一个元素 if (!trade_list.empty()) { const auto& first_trade = trade_list[0]; printf("第一个交易数据:\n"); printf("C: %.1f, CO: %d, H: %.1f, L: %.1f\n", first_trade.C, first_trade.CO, first_trade.H, first_trade.L); printf("O: %.1f, T: %lld, TO: %lld, V: %d\n", first_trade.O, first_trade.T, first_trade.TO, first_trade.V); } return 0; }
额外注意事项
- 确保你的RapidJSON版本支持range-based for循环(较新版本都支持,如果用旧版本,可以改用迭代器遍历
array.Begin()到array.End()) - 如果JSON中存在可选字段,可以在解析前添加判断,比如
if (item.HasMember("C") && item["C"].IsDouble()),避免空指针或类型不匹配错误 - 字段类型要和JSON中的数值类型严格对应,比如
T和TO是较大的整数,用int64_t防止溢出
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

