使用reqwest解析StackExchange API JSON时触发解析错误排查
解决StackExchange API JSON解析的Decode错误
问题根源
StackExchange API返回的响应采用了gzip压缩,但reqwest默认不会自动处理这类压缩内容。当你直接调用response.json()时,实际上是在解析压缩后的二进制数据,而非可读的JSON文本,因此会触发expected value, line: 1, column: 1的解析错误。
修复方案
方案1:启用客户端自动解压缩
创建reqwest客户端时开启gzip/deflate支持,让客户端自动处理压缩响应:
#[get("/test")] async fn my_function(username: web::Query<QueryParams>) -> impl Responder { println!("recieved!"); // 构建支持自动解压缩的客户端 let client = match reqwest::Client::builder() .gzip(true) .deflate(true) .build() { Ok(c) => c, Err(_) => return HttpResponse::InternalServerError().finish(), }; match client.get("https://api.stackexchange.com/2.2/users/13029516?&site=stackoverflow").await { Ok(response) => { if !response.status().is_success() { return HttpResponse::InternalServerError().finish(); } match response.json::<serde_json::Value>().await { Ok(res) => println!("Success! {:?}", res), Err(e) => { eprintln!("JSON解析失败: {}", e); return HttpResponse::InternalServerError().finish(); } } } Err(e) => { eprintln!("API请求失败: {}", e); return HttpResponse::InternalServerError().finish(); } }; HttpResponse::Ok().finish() }
方案2:手动解压缩响应内容
如果不想修改客户端配置,可以手动读取响应字节并使用flate2库解压缩:
use flate2::read::GzDecoder; use std::io::Read; #[get("/test")] async fn my_function(username: web::Query<QueryParams>) -> impl Responder { println!("recieved!"); match reqwest::get("https://api.stackexchange.com/2.2/users/13029516?&site=stackoverflow").await { Ok(response) => { if !response.status().is_success() { return HttpResponse::InternalServerError().finish(); } // 读取原始响应字节 let bytes = match response.bytes().await { Ok(b) => b, Err(_) => return HttpResponse::InternalServerError().finish(), }; // 解压缩gzip内容 let mut decoder = GzDecoder::new(&bytes[..]); let mut json_content = String::new(); if decoder.read_to_string(&mut json_content).is_err() { return HttpResponse::InternalServerError().finish(); } // 解析JSON let res = match serde_json::from_str::<serde_json::Value>(&json_content) { Ok(r) => r, Err(_) => return HttpResponse::InternalServerError().finish(), }; println!("Success! {:?}", res); } Err(_) => return HttpResponse::InternalServerError().finish(), }; HttpResponse::Ok().finish() }
注意事项
- 替换代码中的
unwrap()为错误处理逻辑,避免不必要的panic - 可以通过检查响应头
Content-Encoding的值,判断是否需要解压缩响应内容
内容的提问来源于stack exchange,提问作者Matthew Trent
相关产品推荐
相关产品推荐

