我从http::response<http::dynamic_body>::body()方法得到了boost::beast::multibuffer个对象.然后,我想从其中解析JSON内容,如下所示:

boost::property_tree::read_json(requestBodyStream, propertyTree);

我是否应该使用boost::beast::buffers_to_stringstd::stringstream来获取requestBodyStream,或者是否有可能不花费那么多内存来复制缓冲区的内容?

推荐答案

一般来说,不要对specific implementation编程,而是对concept编程.这里,dynamic_body documents:

该正文使用DynamicBuffer作为基于内存的容器,用于保存消息有效负载.可以对使用此正文类型的消息进行序列化和解析.

您不需要这个概念,因为无论如何您都将完全在内存中使用它,但是如果您需要的话,您应该这样做:

net::streambuf sb;
sb.commit(net::buffer_copy(sb.prepare(body.size()), body.cdata()));

std::istream is(&sb);
ptree doc;
read_json(is, doc);

看它100

#include <boost/asio.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>

#include <boost/beast/http.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
namespace net = boost::beast::net;
namespace http = boost::beast::http;
using boost::property_tree::ptree;

int main() {
    net::posix::stream_descriptor input(net::system_executor{}, 0); // stdin

    http::response<http::dynamic_body> res;
    {
        net::streambuf readbuf;
        http::read(input, readbuf, res);
    }

    auto& body = res.body();

    net::streambuf sb;
    sb.commit(net::buffer_copy(sb.prepare(body.size()), body.cdata()));

    std::istream is(&sb);
    ptree doc;
    read_json(is, doc);

    write_json(std::cout << "Parsed body: ", doc);
}

它从stdin读取一个示例响应,让我们使用

HTTP/1.1 200 OK
Content-Length: 50

{"this":{"is":[1,2,3], "a":"sample"}, "object":42}

如下所示:

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp && ./a.out <<< $'HTTP/1.1 200 OK\r\nContent-Length: 50\r\n\r\n{\"this\":{\"is\":[1,2,3], \"a\":\"sample\"}, \"object\":42}'

版画

Parsed body: {
    "this": {
        "is": [
            "1",
            "2",
            "3"
        ],
        "a": "sample"
    },
    "object": "42"
}

然而,

现在我们已经回答了问题,让我们添加上下文:

  • 不要使用Boost属性树(除非您需要属性树.提示:您不需要).查看输出:属性树不是JSON库

  • 除非需要,否则不要使用动态身体.在本例中,您在内存中读取整个消息,在内存中复制它(以转换为StreamBuf),使用地区感知的iStream(慢)从它读取,结果在内存中作为另一个副本存在.

相反,您可以使用最简单的模型,并使用JSON库,例如,Boost.JSON:

100

#include <boost/asio.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>

#include <boost/beast/http.hpp>
#include <boost/json/src.hpp> // for header-only
#include <iostream>
namespace net  = boost::beast::net;
namespace http = boost::beast::http;
namespace json = boost::json;

int main() {
    net::posix::stream_descriptor input(net::system_executor{}, 0); // stdin

    http::response<http::string_body> res;
    {
        net::streambuf readbuf;
        http::read(input, readbuf, res);
    }

    auto doc = json::parse(res.body());
    std::cout << "Parsed body: " << doc << "\n";
}

它的代码更少,效率更高,最重要的是,正确处理JSON!

Json相关问答推荐

JOLT将对象名作为新属性添加到主体中

最新版本的Deneb在数据溢出时不支持滚动

如何使用表键名称GROUP_BY

PowerShell:将Invoke-WebRequest与变量一起使用

解析SQL中的嵌套JSON

使用 Power BI 中的 Deneb 视觉效果绘制面积图中的 X 轴日期

如何在 Apps 脚本中循环遍历 JSON 响应

将请求中的数据推送到数组中

用于遮蔽卡的 Jolt 规格

根据数据框中的其他列值将列表 json 对象插入行

流导入错误:重新上传时不存在布局释放 UUID

如何在生产环境中更改 Flutter 应用程序中的数据模型?

如何比较 JSON 文档并返回与 Jackson 或 Gson 的差异?

获取json中某个键的索引

如何在 json 编码字符串内的子数组数据周围添加方括号?

如何在 Django JSONField 数据上聚合(最小/最大等)?

[__NSCFNumber 长度]:发送到实例 UITableView 的无法识别的 Select 器

获取一个数字的 PHP 对象属性

Python 到 JSON 序列化在十进制上失败

通过 JSON 发送 64 位值的公认方式是什么?