Rust 使用 reqwest 发送 POST 请求并解析 JSON 数据
use std::{io, collections::HashMap, error::Error};
use std::fmt::format;
use std::io::BufRead;
use reqwest::header::HeaderMap;
use serde::{Deserialize};
use serde_derive::Deserialize;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// let input_buf=get_user_input();
// println!('{}',input_buf);
match send_post().await {
Ok(res) => {
println!('{:#?}', res);
let data: Result<Vec<Completion>, Box<dyn Error>> = serde_json::Deserializer::from_str(&res)
.into_iter()
.map(|v| Completion::deserialize(v).map_err(|e| format!('Deserialization error {}', e)))
.collect();
let completions: Vec<String> = data?.iter().map(|c| c.completion.clone()).collect();
println!('{:#?}', completions);
}
Err(e) => { eprintln!('{:?}', e) }
}
Ok(())
}
#[derive(Debug, Deserialize)]
struct Completion {
#[serde(rename = 'completion')]
completion: String,
}
//获取用户键盘输入
fn _get_user_input() -> String {
let mut input_buf = String::new();
let _input = io::stdin().read_line(&mut input_buf).expect('fail to get user input.');
input_buf
}
async fn send_post() -> Result<String, reqwest::Error> {
let client = reqwest::Client::new();
//post 请求头
let mut header = HeaderMap::new();
header.insert('User-Agent',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) \
Chrome/110.0.0.0 Safari/537.36'.parse().expect('unsolve the userAgent header value.'),
);
header.insert('referer', 'https//www.covery.com'.parse().expect('unsolve the referer value.'));
header.insert('sec-ch-ua', 'sec-ch-ua'.parse().expect('ms'));
// post 请求体
let mut data = HashMap::new();
data.insert('prompt', 'hello');
Ok(client.post('https://free-api.cveoy.com/v3/completions')
.headers(header)
.json(&data)
.send()
.await?
.text()
.await?
)
}
代码解释:
-
导入必要的库
std::{io, collections::HashMap, error::Error}: 用于输入输出、哈希表和错误处理std::fmt::format: 用于格式化字符串std::io::BufRead: 用于缓冲读取reqwest::header::HeaderMap: 用于设置请求头serde::{Deserialize}: 用于反序列化 JSON 数据serde_derive::Deserialize: 用于自动生成反序列化代码
-
定义
Completion结构体- 使用
#[derive(Debug, Deserialize)]宏,让Completion结构体支持调试和反序列化 - 使用
#[serde(rename = 'completion')]宏,将 JSON 字段completion映射到completion属性
- 使用
-
定义
send_post函数- 使用
reqwest::Client::new()创建一个 HTTP 客户端 - 创建一个
HeaderMap对象,并添加必要的请求头 - 创建一个
HashMap对象,用于存放 POST 请求体数据 - 使用
client.post()发送 POST 请求,并设置请求头和请求体 - 使用
await?等待请求完成并处理可能的错误 - 使用
text()方法获取响应文本 - 使用
await?等待响应文本获取并处理可能的错误
- 使用
-
定义
main函数- 使用
#[tokio::main]宏,将main函数标记为异步函数 - 使用
match send_post().await {...}语句处理请求结果 - 如果请求成功,将响应文本解析为
Vec<Completion>类型 - 使用
data?.iter().map(|c| c.completion.clone()).collect()获取所有completion属性的值,并存储到completions变量中 - 打印请求结果和解析后的
completions变量 - 如果请求失败,则打印错误信息
- 使用
代码优化:
- 添加了
use std::error::Error;并将main函数的返回类型改为Result<(), Box<dyn Error>>,以便更方便地处理错误 - 使用
?操作符简化错误处理代码 - 使用
serde库反序列化 JSON 数据,提高代码可读性和可维护性 - 使用
HashMap存储请求体数据,方便添加和修改数据 - 使用
HeaderMap设置请求头,提高代码可读性 - 使用
await?简化异步操作的错误处理
注意:
- 需要确保已经安装了
reqwest和serde库 - 替换代码中的
https://free-api.cveoy.com/v3/completions为你想要请求的 API 地址 - 根据实际情况修改请求头和请求体数据
- 在处理 JSON 数据时,需要根据 API 文档定义相应的结构体
原文地址: https://www.cveoy.top/t/topic/lBOW 著作权归作者所有。请勿转载和采集!