#c #json #boost #grpc #asio
Вопрос:
У меня есть следующая строка 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":"n9MZdq6qPssK3jw63sjR8VRR4NjyCmaV11LnqTiCFQjRCDFreUVcn"}
Мне нужно прочитать поле message.data, представляющее собой буфер, поступающий из node.js процесс через gRPC. Я попробовал что-то вроде этого:
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 () — это моя строка json, полученная через gRPC. В результате получается следующее:
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":"n9MZdq6qPssK3jw63sjR8VRR4NjyCmaV11LnqTiCFQjRCDFreUVcn"}
Message received, json:
Как я могу прочитать это поле и поместить его в строку std::или буфер asio?
Ответ №1:
Две проблемы:
- Сообщение.данные-это не строка. Это массив целых чисел.
- Дерево свойств Boost не является библиотекой JSON.
Предполагая, что вы ожидаете, что «строка» будет состоять из байтов, которые представлены в виде их целых значений без знака в массиве.
Одно исправление, один обходной путь:
Исправление
Используйте библиотеку JSON, например Boost JSON:
#include <boost/json.hpp>
#include <boost/json/src.hpp>
#include <iostream>
struct Gossip { std::string message(); } gossip;
int main()
{
namespace json = boost::json;
auto doc = json::parse(gossip.message()).as_object();
autoamp; arr = doc["message"].as_object()["data"];
auto bytes = json::value_to<std::vector<uint8_t>>(arr);
std::string text(bytes.begin(), bytes.end());
//std::cout << "message(): " << gossip.message() << "n";
std::cout << "doc: " << doc << "n";
std::cout << "arr: " << arr << "n";
std::cout << "bytes: ";
for (int val : bytes)
std::cout << " " << val;
std::cout << "ntext: " << std::quoted(text) << "n";
}
std::string Gossip::message() {
return R"({
"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": "n9MZdq6qPssK3jw63sjR8VRR4NjyCmaV11LnqTiCFQjRCDFreUVcn"
})";
}
Обходной Путь С Деревом Свойств Boost
std::string message_received;
for (autoamp; [k, v] : pt.get_child("message.data")) {
message_received = static_cast<char>(v.get_value<unsigned short>());
}
Полученные данные не похожи ни на одну (известную мне) текстовую кодировку, но это, вероятно, не относится к делу.
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
struct Gossip { std::string message(); } gossip;
int main()
{
boost::property_tree::ptree pt;
{
std::stringstream ss(gossip.message());
boost::property_tree::read_json(ss, pt);
}
std::string message_received;
for (autoamp; [k, v] : pt.get_child("message.data")) {
message_received = static_cast<char>(v.get_value<unsigned short>());
}
std::cout << "Message received pure: " << gossip.message() << std::endl;
std::cout << "Message received, json: " << message_received << std::endl;
}
std::string Gossip::message() {
return R"({
"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": "n9MZdq6qPssK3jw63sjR8VRR4NjyCmaV11LnqTiCFQjRCDFreUVcn"
})";
}