cpprestsdk发起POST需设content_type并用extract_json()解析响应,异步请求须用then链式处理,URI拼接推荐uri_builder。

cpprestsdk 发起 POST 请求并解析 JSON 响应
cpprestsdk(即 Casablanca)本身不内置 JSON Schema 验证,但提供 json::value 类型支持原生解析和构造。异步请求必须搭配 then() 链式处理,不能直接用 get() 同步阻塞(尤其在 UI 线程或高并发服务中易引发死锁)。
-
http_client构造时 URL 末尾不加斜杠不影响请求,但路径拼接建议统一由uri_builder处理,避免手动字符串拼接出错 - POST body 必须显式设置
content_type,否则服务端可能拒收:L"application/json"是最常用值,注意宽字符前缀L - 响应体读取必须调用
response.extract_json(),不能直接对response.body()做json::value::parse()—— 后者会丢弃编码信息且不处理流式响应
auto client = http_client(U("https://api.example.com"));
auto req = http_request(methods::POST);
req.set_request_uri(U("/v1/data"));
req.headers().add(U("Authorization"), U("Bearer abc123"));
req.set_body(json::value::object({
{ U("query"), json::value::string(U("user")) },
{ U("limit"), json::value::number(10) }
}).serialize(), U("application/json"));
client.request(req).then([](http_response response) -> pplx::task {
if (response.status_code() != status_codes::OK) {
throw std::runtime_error("HTTP error: " + std::to_string(response.status_code()));
}
return response.extract_json(); // ← 关键:必须用 extract_json()
}).then([](json::value json_obj) {
auto items = json_obj.at(U("results")).as_array();
for (const auto& item : items) {
wcout << item.at(U("id")).as_string() << endl;
}
}).wait(); // 仅调试用;生产环境应延续 then 链或用 .get() 在独立线程
异步链中捕获网络异常与 HTTP 错误
cpprestsdk 的异常不是标准 std::exception 子类,而是 web::http::http_exception 或底层 std::system_error。直接 try/catch 外层任务会漏掉内部异步阶段抛出的异常 —— 必须在每个 then() 回调里检查 response.status_code(),或统一用 .then([](pplx::task<:value> t) { try { t.get(); } catch(...) {...} }) 包裹。
-
http_exception通常来自 DNS 失败、连接超时、SSL 握手失败等,t.get()会 rethrow 它 - HTTP 4xx/5xx 响应不会自动抛异常,需手动判断
status_code()并决定是否 throw - 超时需在
http_client_config中设置:config.set_timeout(std::chrono::seconds(15));,否则默认无超时
json::value 解析常见陷阱
json::value 是引用语义,频繁调用 at() 可能抛 json_exception(键不存在),且不支持类似 Python 的 .get(key, default) 模式。嵌套深时容易写成 obj.at(U("a")).at(U("b")).at(U("c")),一旦中间某层缺失就崩溃。
- 安全访问推荐先用
has_field()判断,再at();或封装工具函数如safe_get(obj, {U("a"), U("b"), U("c")}) -
as_string()返回utility::string_t(即std::wstring),若服务端返回 UTF-8 字符串但未声明Content-Type: application/json; charset=utf-8,可能乱码 —— 此时需手动用utf8_to_utf16()转换 - 数值类型区分
as_number()(浮点)和as_integer()(整型),但 JSON 标准无整数/浮点之分,服务端传42.0会导致as_integer()抛异常
Windows 下链接 cpprestsdk 的关键配置
Visual Studio 项目必须同时满足三项,缺一不可,否则出现 LNK2019 找不到 http_client::request 等符号:
立即学习“C++免费学习笔记(深入)”;
- 附加依赖项加入:
cpprest142_2_10.lib(版本号随 SDK 更新变化,查%VCPKG_ROOT%\installed\x64-windows\lib确认) - C/C++ → 语言 → 符合模式 设为“否”,否则 C++17 的某些特性(如 structured binding)会与 SDK 冲突
- 预处理器定义添加:
_NO_ASYNCRTIMP(禁用动态链接 AsyncRT,避免 DLL 版本不匹配)
Linux/macOS 用户用 vcpkg 安装后,链接时需确保 -lcpprest -lboost_system -lssl -lcrypto -lz 顺序正确,libssl 必须在 libcpprest 之后。











