Как десериализовать поток байтов из ответа reqwest в JSON? - PullRequest
0 голосов
/ 13 февраля 2020

Запрос через reqwest ожидает длинного ответа на опрос, поэтому я создал поток байтов и попытался десериализовать каждый блок в JSON. Я сразу понял, что это неправильно, потому что каждый кусок может быть неполным, поэтому десериализация может потерпеть неудачу; хотя некоторые куски были десериализованы в JSON, большинство из них были неудачными. Как мне это сделать?

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = reqwest::Client::new();
    let mut stream = client
        .get("https://...")
        .send()
        .await?
        .bytes_stream();

    while let Some(chunk) = stream.next().await {
        match serde_json::from_slice::<Value>(&chunk?){
            Ok(value) => println!("OK: {:?}", value),
            Err(e) => println!("ERROR: {:?}", e),
        }
    };

    Ok(())
}

1 Ответ

3 голосов
/ 13 февраля 2020

Если вы включите функцию json из библиотеки reqwest в вашем Cargo.toml. Тогда вы можете упростить код до этого:

let json = client
    .get("https://...")
    .send()
    .await?
    .json::<T>() //T needs to implement serde::de::DeserializeOwned
    .await?;

Это отправит запрос и автоматически преобразует его в JSON. Поскольку метод json внутренне использует serde_json::from_reader, он также десериализует поток байтов в структуру.

Это не будет выполнено, если тело ответа не в формате JSON или его нельзя десериализовать до T.

...