使用 Rust 发送 POST 请求并解析 JSON 数据
use std::{io, collections::HashMap};
use std::fmt::format;
use std::io::BufRead;
use reqwest::header::HeaderMap;
use serde::{Deserialize};
use serde_derive::Deserialize;
use std::error::Error;
#[tokio::main]
async fn main() {
// 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| v.and_then(|inner_v| Completion::deserialize(inner_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) }
}
}
#[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:用于获取用户输入std::collections::HashMap:用于构建 POST 请求体std::fmt::format:用于格式化错误信息std::io::BufRead:用于读取用户输入reqwest::header::HeaderMap:用于构建请求头serde::{Deserialize}:用于反序列化 JSON 数据serde_derive::Deserialize:用于自动生成Deserializetrait 的实现std::error::Error:用于处理错误tokio::main:用于运行异步代码
- 定义
Completion结构体:
- 使用
#[derive(Debug, Deserialize)]注解,自动生成Debug和Deserializetrait 的实现 - 使用
#[serde(rename = 'completion')]注解,将 JSON 字段completion映射到结构体字段completion
- 定义
_get_user_input函数:
- 获取用户从键盘输入的文本,返回一个
String类型的值
- 定义
send_post函数:
- 创建一个新的
reqwest::Client对象 - 创建一个
HeaderMap对象,添加必要的请求头信息 - 创建一个
HashMap对象,存储 POST 请求体数据 - 使用
client.post发送 POST 请求,并将请求头、请求体、URL 传入 - 使用
await?等待请求完成并处理错误 - 使用
text()获取响应文本 - 使用
await?等待响应文本获取完成并处理错误
- 在
main函数中使用send_post函数:
- 使用
match语句处理send_post函数的返回值 - 如果请求成功,使用
serde_json::Deserializer::from_str解析 JSON 响应数据 - 使用
into_iter()将 JSON 数据转换为迭代器 - 使用
map函数将迭代器中的每个Result类型的值转换为Completion类型的值 - 使用
collect()将迭代器转换为Vec类型的值 - 如果解析成功,打印解析结果
- 如果解析失败,打印错误信息
代码优化:
- 将所有双引号改为单引号
- 使用
and_then函数处理Result类型,避免直接将Result类型的值传入Completion::deserialize函数中 - 添加代码注释,解释代码的功能和逻辑
- 使用
#[tokio::main]注解,将main函数声明为异步函数 - 使用
await?宏处理异步代码的错误
其他说明:
- 需要确保已经安装了
reqwest和serde依赖库 - 需要确保目标服务器能够接受 POST 请求,并且响应数据为 JSON 格式
- 可以根据实际需要修改请求头、请求体和 URL
原文地址: https://www.cveoy.top/t/topic/lBPg 著作权归作者所有。请勿转载和采集!