簡體   English   中英

Rust:DateTime::parse_from_rfc3339 給出 ParseError(無效)

[英]Rust: DateTime::parse_from_rfc3339 gives ParseError(Invalid)

我正在嘗試使用 Bungie API 獲取一些數據。 json 響應中有上次播放日期,格式為“2022-09-18T02:17:59Z”。 我想解析它並創建 DateTime object。

我有以下代碼(個人數據替換為 XXX):

const API_ROOT: &str = "https://www.bungie.net/Platform";
const API_KEY_HEADER: &str = "X-API-Key";

const MY_API_KEY: &str = "XXX";

const MEMBERSHIP_TYPE: &str = "XXX";
const MEMBERSHIP_ID: &str = "XXX";

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let url = format!("{}/Destiny2/{}/Profile/{}/?components=100", API_ROOT, MEMBERSHIP_TYPE, MEMBERSHIP_ID);

    let req = reqwest::Client::new()
        .get(url)
        .header(API_KEY_HEADER, MY_API_KEY)
        .send()
        .await?
        .text()
        .await?;

    let data: JsonValue = serde_json::from_str(&req).expect("Failed to read json from response!");

    let name = &data["Response"]["profile"]["data"]["userInfo"]["displayName"].to_string();
    println!("Name: {}", name);

    let last_played_raw = &data["Response"]["profile"]["data"]["dateLastPlayed"].to_string();
    println!("{}", last_played_raw);
    let last_played_raw = last_played_raw.replace("Z", "+00:00");
    println!("{}", last_played_raw);

    let last_played = DateTime::parse_from_rfc3339(&last_played_raw).unwrap();

    println!("Last played: {}", last_played);

    Ok(())
}

問題是解析 last_played_raw 字符串恐慌:

"2022-09-18T02:17:59Z"
"2022-09-18T02:17:59+00:00"
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ParseError(Invalid)', src\main.rs:37:70

有人可以告訴我,有什么問題嗎?

發生這種情況的原因相當簡單。 發生這種情況是因為前導引號和尾隨引號 ( " ) 包含在您傳遞給DateTime::parse_from_rfc3339()的字符串中。可能解決此問題的最不尖銳的更改是將這些替換為空字符串文字,如下所示:

extern crate serde_json;
extern crate serde;

use serde_json::Value as JsonValue;
use chrono::DateTime;

fn main() {
    let json_string = r#"{"dateLastPlayed": "2022-09-18T02:17:59Z"}"#;

    let data: JsonValue = serde_json::from_str(json_string).unwrap();

    let last_played = data["dateLastPlayed"].to_string().replace("\"", "");
    println!("{}", last_played.as_str());

    let datetime = DateTime::parse_from_rfc3339(last_played.as_str()).expect("Failed to parse");
    println!("{}", datetime);
}

這是指向操場的鏈接,您可以在其中輕松查看。

但是在serde中,您通常不使用原始Value ,而是像這樣處理反序列化:

use serde::Deserialize;
use chrono::DateTime;

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct MyData {
    date_last_played: String,
}

fn main() {
    let json_string = r#"{"dateLastPlayed": "2022-09-18T02:17:59Z"}"#;

    let data: MyData = serde_json::from_str(json_string).unwrap();

    let datetime = DateTime::parse_from_rfc3339(data.date_last_played.as_str()).expect("Failed to parse");
    println!("{}", datetime);
}

這是上面的操場

您還應該能夠使用此結構直接解析 JSON

struct MyData {
    date_last_played: DateTime,
}

這將是首選,但您需要一個自定義的 serde Deserializer

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM