无法从 StackAPI 解析 JSON:预期值“,行:1,列:1

Can't parse JSON from StackAPI: expected value", line: 1, column: 1

提问人:Matthew Trent 提问时间:5/2/2023 更新时间:5/2/2023 访问量:234

问:

我正在尝试从这个端点解析 JSON:https://api.stackexchange.com/2.2/users/13029516?&site=stackoverflow

它看起来像这样:

{
"items": [
{
"badge_counts": {
"bronze": 27,
"silver": 14,
"gold": 0
},
"account_id": 17932441,
"is_employee": false,
"last_modified_date": 1677242400,
"last_access_date": 1682981080,
"reputation_change_year": 313,
"reputation_change_quarter": 29,
"reputation_change_month": 0,
"reputation_change_week": 10,
"reputation_change_day": 0,
"reputation": 2234,
"creation_date": 1583703647,
"user_type": "registered",
"user_id": 13029516,
"website_url": "https://matthewtrent.me/links",
"link": "https://stackoverflow.com/users/13029516/matthew-trent",
"profile_image": "https://lh3.googleusercontent.com/a/AATXAJwHVeuBCVo52xa3k_IryQ1llGDNWkHRYiO0R2xh=k-s256",
"display_name": "Matthew Trent"
}
],
"has_more": false,
"quota_max": 300,
"quota_remaining": 271
}

但我不能。我正在使用该软件包。这是我使用它的端点(简化):reqwest

#[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() != 200 {
                return HttpResponse::InternalServerError().finish();
            } else {
                let res = response.json::<serde_json::Value>().await.unwrap(); // <-- where it panics
                println!("Success! {:?}", res);
            }
        }
        Err(_) => return HttpResponse::InternalServerError().finish(),
    };
    HttpResponse::Ok().finish()
}

它对线感到恐慌.奇怪的是,我命中了不同的端点(例如:),它运行良好并列出了 JSON 结果。我唯一的猜测是 Stack API 的 JSON 格式不正确?let res = response.json::<serde_json::Value>().await.unwrap();https://pokeapi.co/api/v2/pokemon/ditto

这是我针对 https://api.stackexchange.com/2.2/users/13029516?&site=stackoverflow 运行它时的输出:

recieved!
thread 'actix-rt|system:0|arbiter:0' panicked at 'called `Result::unwrap()` on an `Err` value: reqwest::Error { kind: Decode, source: Error("expected value", line: 1, column: 1) }', src/services/stack_overflow.rs:42:70
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
recieved!
thread 'actix-rt|system:0|arbiter:1' panicked at 'called `Result::unwrap()` on an `Err` value: reqwest::Error { kind: Decode, source: Error("expected value", line: 1, column: 1) }', src/services/stack_overflow.rs:42:70
recieved!
thread 'actix-rt|system:0|arbiter:2' panicked at 'called `Result::unwrap()` on an `Err` value: reqwest::Error { kind: Decode, source: Error("expected value", line: 1, column: 1) }', src/services/stack_overflow.rs:42:70
recieved!
thread 'actix-rt|system:0|arbiter:3' panicked at 'called `Result::unwrap()` on an `Err` value: reqwest::Error { kind: Decode, source: Error("expected value", line: 1, column: 1) }', src/services/stack_overflow.rs:42:70
recieved!
thread 'actix-rt|system:0|arbiter:4' panicked at 'called `Result::unwrap()` on an `Err` value: reqwest::Error { kind: Decode, source: Error("expected value", line: 1, column: 1) }', src/services/stack_overflow.rs:42:70
recieved!
thread 'actix-rt|system:0|arbiter:5' panicked at 'called `Result::unwrap()` on an `Err` value: reqwest::Error { kind: Decode, source: Error("expected value", line: 1, column: 1) }', src/services/stack_overflow.rs:42:70
recieved!
thread 'actix-rt|system:0|arbiter:6' panicked at 'called `Result::unwrap()` on an `Err` value: reqwest::Error { kind: Decode, source: Error("expected value", line: 1, column: 1) }', src/services/stack_overflow.rs:42:70
recieved!
thread 'actix-rt|system:0|arbiter:7' panicked at 'called `Result::unwrap()` on an `Err` value: reqwest::Error { kind: Decode, source: Error("expected value", line: 1, column: 1) }', src/services/stack_overflow.rs:42:70
recieved!
thread 'actix-rt|system:0|arbiter:0' panicked at 'called `Result::unwrap()` on an `Err` value: reqwest::Error { kind: Decode, source: Error("expected value", line: 1, column: 1) }', src/services/stack_overflow.rs:42:70

任何帮助都会很棒,谢谢。

1

json rust actix-web reqwest serde-json

评论

0赞 drewtato 5/2/2023
您应该将响应另存为 String (using ),将其打印出来,然后尝试将其解析为 json,以便您可以查看第 1 行 col 1 处的字符。.text()
0赞 Matthew Trent 5/2/2023
我试过了,它完全是胡言乱语的文本/字符@drewtato
1赞 drewtato 5/2/2023
尝试启用该功能,因为 stackexchange 始终返回压缩数据: api.stackexchange.com/docs/compressiongzipreqwest
1赞 drewtato 5/2/2023
P.S. 还有一个功能,但任何一个都可能有效deflate
0赞 Matthew Trent 5/2/2023
@drewtato 这奏效了!请随时将其添加为答案,我会检查它。

答:

2赞 drewtato 5/2/2023 #1

此操作失败,因为 Stack Exchange API 不完全遵循 HTTP 规范

虽然我们的 API 是基于 HTTP 的,但我们选择在一个特定领域与标准 HTTP 不同。在正常操作期间,我们保证所有响应都使用 GZIP 或 DEFLATE 进行压缩。

如果检查请求和响应标头,您将看到 API 返回 尽管 reqwest 未发送包含 .Content-Encoding: gzipAccept-Encodinggzip

Reqwest 决定忽略未知编码并尝试读取它,从而导致垃圾数据。

幸运的是,您可以启用 reqwest 功能,以便它既可以发送标头,也可以解码 GZIP 编码的响应。如果您想使用 DEFLATE,还有一个功能。gzipAccept-Encoding: gzipdeflate

[dependencies]
reqwest = { verson = "0.11", features = ["json", "gzip", "deflate"] }

还可以在运行时使用 ClientBuilder::gzip 方法关闭此行为。