使用Boost读取JSON中Buffer字段并存入std::string或asio buffer的方法咨询
C++ 读取JSON中Buffer数组字段解决方案
问题描述
我有如下JSON字符串:
{"message": {"type":"Buffer", "data":[0,0,0,193,0,41,10,190,1,34,128,0,0,1,38,0,0,1,232,41,40,202,35,104,81,66,0,162,194,173,0,254,67,116,38,60,235,70,250,195,139,141,184,47,167,240,210,207,118,184,140,225,82,52,30,35,111,80,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,115,33,2,155,92,51,188,68,15,123,37,47,245,59,120,114,102,60,233,15,212,39,112,165,190,210,14,188,25,156,234,124,154,181,101,118,71,48,69,2,33,0,242,181,45,125,208,73,206,26,86,183,220,28,159,36,149,124,208,72,187,118,116,44,224,252,192,173,242,248,112,181,63,49,2,32,84,83,33,39,113,80,183,50,225,212,133,84,226,26,173,185,65,216,237,234,90,20,215,136,184,246,229,230,13,227,69,42]}, "validator_key":"n9MZdq6qPssK3jw63sjR8VRR4NjyCmaV11LnqTiCFQjRCDFreUVc\n"}
我需要读取message.data字段,该字段是Node.js进程通过gRPC返回的buffer。我尝试了如下实现代码:
std::stringstream ss; boost::property_tree::ptree pt; ss << gossip.message(); boost::property_tree::read_json(ss, pt); auto message_received = pt.get<std::string>("message.data"); std::cout << "Message received pure: " << gossip.message() << std::endl; std::cout << "Message received, json: " << message_received << std::endl;
其中gossip.message()是我通过gRPC接收到的原始JSON字符串,实际运行输出结果如下:
Message received pure: {"message":{"type":"Buffer","data":[0,0,0,193,0,41,10,190,1,34,128,0,0,1,38,0,0,1,232,41,40,202,35,104,81,66,0,162,194,173,0,254,67,116,38,60,235,70,250,195,139,141,184,47,167,240,210,207,118,184,140,225,82,52,30,35,111,80,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,115,33,2,155,92,51,188,68,15,123,37,47,245,59,120,114,102,60,233,15,212,39,112,165,190,210,14,188,25,156,234,124,154,181,101,118,71,48,69,2,33,0,242,181,45,125,208,73,206,26,86,183,220,28,159,36,149,124,208,72,187,118,116,44,224,252,192,173,242,248,112,181,63,49,2,32,84,83,33,39,113,80,183,50,225,212,133,84,226,26,173,185,65,216,237,234,90,20,215,136,184,246,229,230,13,227,69,42]},"validator_key":"n9MZdq6qPssK3jw63sjR8VRR4NjyCmaV11LnqTiCFQjRCDFreUVc\n"} Message received, json:
请问我应该如何正确读取该字段,将其存入std::string或者asio buffer中?
解决方案
问题原因
message.data在JSON中是数字数组类型,无法直接通过boost::property_tree::ptree::get<std::string>()方法读取,该方法只能读取字符串类型的节点值,所以返回为空。
正确实现步骤
- 先获取
message.data对应的数组子节点 - 遍历数组所有元素,将每个数字转为字节存入容器
- 可直接将容器转为asio buffer使用
基于Boost.PropertyTree的实现代码
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> #include <sstream> #include <string> #include <vector> #include <asio.hpp> // 如果需要用asio buffer的话引入 // ... 原有代码 std::stringstream ss; boost::property_tree::ptree pt; ss << gossip.message(); boost::property_tree::read_json(ss, pt); // 获取data数组节点 auto& data_node = pt.get_child("message.data"); // 存入std::string std::string buffer_str; buffer_str.reserve(data_node.size()); // 预分配空间提升性能 // 也可以选择存入std::vector<uint8_t>,更适合存储字节数据 // std::vector<uint8_t> buffer_vec; // buffer_vec.reserve(data_node.size()); for (auto& item : data_node) { uint8_t byte_val = static_cast<uint8_t>(item.second.get_value<int>()); buffer_str.push_back(static_cast<char>(byte_val)); // buffer_vec.push_back(byte_val); } // 转为asio buffer asio::const_buffer asio_buf(buffer_str.data(), buffer_str.size()); // 如果用vector的话:asio::const_buffer asio_buf(buffer_vec.data(), buffer_vec.size());
更简便的替代方案
如果项目允许更换JSON库,更推荐使用nlohmann/json库,无需手动遍历数组,一行代码即可完成读取:
#include <nlohmann/json.hpp> using json = nlohmann::json; // ... auto j = json::parse(gossip.message()); auto buffer_vec = j["message"]["data"].get<std::vector<uint8_t>>(); // 转asio buffer同理 asio::const_buffer asio_buf(buffer_vec.data(), buffer_vec.size());
内容的提问来源于stack exchange,提问作者Flav Scheidt
相关产品推荐
相关产品推荐

