ReactiveX 学习笔记(24)使用 RxCpp + C++ REST SDK 调用 REST API
JSON : Placeholder
JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站。
以下使用 Task API/Rx.NET + Json.NET 调用该网站的 REST API,获取字符串以及 JSON 数据。
- GET /posts/1
- GET /posts
- POST /posts
- PUT /posts/1
- DELETE /posts/1
所有 GET API 都返回JSON数据,格式(JSON-Schema)如下:
{
"type":"object",
"properties": {
"userId": {"type" : "integer"},
"id": {"type" : "integer"},
"title": {"type" : "string"},
"body": {"type" : "string"}
}
}
安装 C++ REST SDK
$ brew install cpprestsdk
$ brew install boost
$ brew install libressl
安装 "JSON for Modern C++"
$ brew tap nlohmann/json
$ brew install nlohmann_json
下载 RxCpp
$ git clone --recursive https://github.com/ReactiveX/RxCpp.git
创建工程
打开 Xcode,File / New / Project...
在向导的第1页选 macOS / Command Line Tool
在向导的第2页语言选 C++,Product Name 填上任意名称
在向导的第3页选择任意文件夹,点击 Create 创建工程。
配置工程
将 System Header Search Paths 设置为
/usr/local/Cellar/cpprestsdk/2.10.2/include
/usr/local/Cellar/boost/1.67.0_1/include
/usr/local/Cellar/libressl/2.7.4/include
/usr/local/Cellar/nlohmann_json/3.1.2/include
RxCpp安装文件夹/Rx/v2/src
将 Library Search Paths 设置为
/usr/local/Cellar/cpprestsdk/2.10.2/lib
/usr/local/Cellar/boost/1.67.0_1/lib
/usr/local/Cellar/libressl/2.7.4/lib
将 Other Linker Flags 设置为
-lcpprest -lboost_system -lboost_thread-mt -lboost_chrono-mt -lssl -lcrypto
cpprestsdk: Undefined symbols for architecture x86_64
Post
在工程中添加 post.hpp,内容如下
#ifndef Post_hpp
#define Post_hpp
#include <iostream>
#include <nlohmann/json.hpp>
using nlohmann::json;
struct Post {
int userId;
int id;
std::string title;
std::string body;
};
void to_json(json& j, const Post& p);
void from_json(const json& j, Post& p);
std::ostream& operator<<(std::ostream& out, const Post& p);
#endif /* Post_hpp */
在工程中添加 post.cpp,内容如下
#include "Post.hpp"
#include <boost/algorithm/string/replace.hpp>
using namespace std;
void to_json(json& j, const Post& p) {
j = json{{"userId", p.userId}, {"id", p.id}, {"title", p.title}, {"body", p.body}};
}
void from_json(const json& j, Post& p) {
p.userId = j.at("userId").get<int>();
p.id = j.at("id").get<int>();
p.title = j.at("title").get<string>();
p.body = boost::algorithm::replace_all_copy(j.at("body").get<string>(), "\n", "\\n");
}
std::ostream& operator<<(std::ostream& out, const Post& p) {
cout << "Post {userId = " << p.userId
<< ", id = " << p.id
<< ", title = \"" << p.title
<< "\", body = \"" << p.body
<< "\"}";
return out;
}
RestApi
在工程中添加 RestApi.hpp,内容如下
#ifndef RestApi_hpp
#define RestApi_hpp
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/json.h>
using namespace utility; // Common utilities like string conversions
//using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
#include "rxcpp/rx.hpp"
namespace Rx {
using namespace rxcpp;
using namespace rxcpp::sources;
using namespace rxcpp::operators;
using namespace rxcpp::util;
}
using namespace Rx;
#include <nlohmann/json.hpp>
using nlohmann::json;
template<class T>
struct RestApi {
http_client client;
RestApi(const uri &base_uri) : client(base_uri) {}
observable<string_t> getString(const string_t &path_query_fragment) {
return observable<>::create<string_t>(
[&](subscriber<string_t> s){
client
.request(methods::GET, path_query_fragment)
.then([](http_response response) -> pplx::task<string_t> {
return response.extract_string();
})
.then([&](pplx::task<string_t> previousTask) {
try {
string_t const & v = previousTask.get();
s.on_next(v);
s.on_completed();
} catch (http_exception const & e) {
s.on_error(std::current_exception());
}
})
.wait();
});
}
observable<T> getObject(const string_t &path_query_fragment) {
return observable<>::create<T>(
[&](subscriber<T> s){
client
.request(methods::GET, path_query_fragment)
.then([](http_response response) -> pplx::task<string_t> {
return response.extract_string();
})
.then([&](pplx::task<string_t> previousTask) {
try {
string_t const & v = previousTask.get();
json j = json::parse(v);
T t = j;
s.on_next(t);
s.on_completed();
} catch (http_exception const & e) {
s.on_error(std::current_exception());
}
})
.wait();
});
}
observable<T> getArray(const string_t &path_query_fragment) {
return observable<>::create<T>(
[&](subscriber<T> s){
client
.request(methods::GET, path_query_fragment)
.then([](http_response response) -> pplx::task<string_t> {
return response.extract_string();
})
.then([&](pplx::task<string_t> previousTask) {
try {
string_t const & v = previousTask.get();
json j = json::parse(v);
std::vector<T> vec = j;
for(const auto& t : vec)
s.on_next(t);
s.on_completed();
} catch (http_exception const & e) {
s.on_error(std::current_exception());
}
})
.wait();
});
}
observable<string_t> createObject(const string_t& url, const T& obj) {
return observable<>::create<string_t>(
[&](subscriber<string_t> s){
json j = obj;
client
.request(methods::POST, url, j.dump(), U("application/json"))
.then([](http_response response) -> pplx::task<string_t> {
return response.extract_string();
})
.then([&](pplx::task<string_t> previousTask) {
try {
string_t const & v = previousTask.get();
s.on_next(v);
s.on_completed();
} catch (http_exception const & e) {
s.on_error(std::current_exception());
}
})
.wait();
});
}
observable<string_t> updateObject(const string_t& url, const T& obj) {
return observable<>::create<string_t>(
[&](subscriber<string_t> s){
json j = obj;
client
.request(methods::PUT, url, j.dump(), U("application/json"))
.then([](http_response response) -> pplx::task<string_t> {
return response.extract_string();
})
.then([&](pplx::task<string_t> previousTask) {
try {
string_t const & v = previousTask.get();
s.on_next(v);
s.on_completed();
} catch (http_exception const & e) {
s.on_error(std::current_exception());
}
})
.wait();
});
}
observable<string_t> deleteObject(const string_t& url) {
return observable<>::create<string_t>(
[&](subscriber<string_t> s){
client
.request(methods::DEL, url)
.then([](http_response response) -> pplx::task<string_t> {
return response.extract_string();
})
.then([&](pplx::task<string_t> previousTask) {
try {
string_t const & v = previousTask.get();
s.on_next(v);
s.on_completed();
} catch (http_exception const & e) {
s.on_error(std::current_exception());
}
})
.wait();
});
}
};
#endif /* RestApi_hpp */
main
将 main.cpp 的内容改为
#include "Post.hpp"
#include "RestApi.hpp"
using namespace std;
int main(int argc, char* argv[])
{
RestApi<Post> api(U("https://jsonplaceholder.typicode.com/"));
api.getString(U("posts/1")).subscribe([](const string_t& v){cout << v << endl;});
api.getObject(U("posts/1")).subscribe([](const Post& v){cout << v << endl;});
api.getArray(U("posts")).take(2).subscribe([](const Post& v){cout << v << endl;});
Post o;
o.id = 0;
o.userId = 101;
o.title = U("test title");
o.body = U("test body");
api.createObject(U("posts"), o).subscribe([](string_t v){cout << v << endl;});
api.updateObject(U("posts/1"), o).subscribe([](string_t v){cout << v << endl;});
api.deleteObject(U("posts/1")).subscribe([](string_t v){cout << v << endl;});
return 0;
}
输出结果
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
Post {userId = 1, id = 1, title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body = "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
Post {userId = 1, id = 1, title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body = "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
Post {userId = 1, id = 2, title = "qui est esse", body = "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"}
{
"body": "test body",
"id": 101,
"title": "test title",
"userId": 101
}
{
"body": "test body",
"id": 1,
"title": "test title",
"userId": 101
}
{}
ReactiveX 学习笔记(24)使用 RxCpp + C++ REST SDK 调用 REST API的更多相关文章
- ReactiveX 学习笔记(14)使用 RxJava2 + Retrofit2 调用 REST API
JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...
- ReactiveX 学习笔记(18)使用 RxJS + Angular 调用 REST API
JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...
- ReactiveX 学习笔记(17)使用 RxSwift + Alamofire 调用 REST API
JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...
- ReactiveX 学习笔记(0)学习资源
ReactiveX 学习笔记 ReactiveX 学习笔记(1) ReactiveX 学习笔记(2)创建数据流 ReactiveX 学习笔记(3)转换数据流 ReactiveX 学习笔记(4)过滤数据 ...
- guava 学习笔记(二) 瓜娃(guava)的API快速熟悉使用
guava 学习笔记(二) 瓜娃(guava)的API快速熟悉使用 1,大纲 让我们来熟悉瓜娃,并体验下它的一些API,分成如下几个部分: Introduction Guava Collection ...
- 《深入Java虚拟机学习笔记》- 第19章 方法的调用与返回
<深入Java虚拟机学习笔记>- 第19章 方法的调用与返回
- go微服务框架kratos学习笔记四(kratos warden-quickstart warden-direct方式client调用)
目录 go微服务框架kratos学习笔记四(kratos warden-quickstart warden-direct方式client调用) warden direct demo-server gr ...
- [原创]java WEB学习笔记24:MVC案例完整实践(part 5)---删除操作的设计与实现
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- springmvc学习笔记--支持文件上传和阿里云OSS API简介
前言: Web开发中图片上传的功能很常见, 本篇博客来讲述下springmvc如何实现图片上传的功能. 主要讲述依赖包引入, 配置项, 本地存储和云存储方案(阿里云的OSS服务). 铺垫: 文件上传是 ...
随机推荐
- SamplesHashtable
using System; using System.Collections; public class SamplesHashtable { public static void Main() { ...
- Apache Shiro 快速入门教程,shiro 基础教程
第一部分 什么是Apache Shiro 1.什么是 apache shiro : Apache Shiro是一个功能强大且易于使用的Java安全框架,提供了认证,授权,加密,和会话管理 ...
- requests模块的使用
requests模块 什么是request模块:requests是python原生一个基于网络请求的模块,模拟浏览器发起请求. requests-get请求 # get请求 import reques ...
- [ 随手记 1 ] C/C++宏,普通函数,内联函数
函数定义 C 语言中的函数定义的一般形式如下: return_type function_name( parameter list ) { body of the function } 在 C 语言中 ...
- python 4
一.列表相关操作 l = ['布偶猫', '小断腿', '大白'] # . append l.append('哎呀') print(l) # . insert l.insert(, '小猪佩琪') p ...
- jwt 接口加密
什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点 ...
- kvm创建新虚拟机
安装图形化管理界面yum install virt-manager -y 安装好之后 新建虚拟机,我使用的方法是使用ISO镜像文件安装 选择镜像 设置内存 如此,一步一步走下去即可,不再截图 创建好之 ...
- 使用outflux 导入influxdb 的数据到timescaledb
influxdb 以及timescaledb 都是不错的时序数据库,timescaledb 团队提供了直接从influxdb 导入 环境准备 docker-compose 文件 version: &q ...
- 公式推导:【BACF】
[BACF]: Kiani Galoogahi H, Fagg A, Lucey S. Learning Background-Aware Correlation Filters for Visual ...
- 怎样使用PL/SQL在不安装oracle 客户端的情况下使用oracle数据库
在网上查了好多这方面的例子,但是似乎说的都不准确,在咨询朋友后终于实现了本机不安装oracle 的情况下,在windows系统上实现连接服务器上的数据库,现在贴出来与大家共享. 首先,我们需要一个PL ...