es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo serializar y deserializar un chrono::Duration?

En mi proyecto actual estoy intentando almacenar una chrono::Duration en una estructura de configuración, que se serializará y deserializará ocasionalmente usando serde_json.

Desafortunadamente, parece que Serialize y Deserialize no se implementan para chrono::Duration. Dicho esto, chrono dice que tiene soporte para serde a través de una de sus características opcionales. Intenté usar este método, pero ahora el compilador se queja sobre los métodos de retorno:

error [E0308]: tipos no coincidentes
 --> src/config.rs:6:10
  |
6 | #[derive(Serialize, Deserialize, Debug, Clone)]
  |          ^^^^^^^^^ se esperaba la estructura  `DateTime`, se encontró la estructura `chrono::Duration`
  |
  = nota: se esperaba la referencia `&DateTime<Utc>`
         se encontró la referencia `&'__a chrono::Duration`
  = nota: este error se origina en el macro derivado `Serialize` (en compilaciones nocturnas, ejecute con -Z macro-backtrace para obtener más información)

error [E0308]: tipos no coincidentes
 --> src/config.rs:6:21
  |
6 | #[derive(Serialize, Deserialize, Debug, Clone)]
  |                     ^^^^^^^^^^^ se esperaba la estructura `chrono::Duration`, se encontró la estructura `DateTime`
  |
  = nota: se esperaba la estructura `chrono::Duration`
             se encontró la estructura `DateTime<Utc>`
  = nota: este error se origina en el macro `try` (en compilaciones nocturnas, ejecute con -Z macro-backtrace para obtener más información)

¿Por qué está sucediendo esto? ¿Qué puedo hacer para solucionarlo?

Aquí está el código en cuestión:

use serde::{Serialize, Deserialize};
use chrono::{DateTime, Duration, Utc};

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Config {
    pub dest_ip: String,
    #[serde(borrow)]
    pub include_paths: Vec<&'static std::path::Path>,
    pub exclude_paths: Vec<&'static std::path::Path>,
    #[serde(with = "chrono::serde::ts_seconds")]
    pub time_between_checks: Duration,
}

Además, aquí están los bits relevantes de Cargo.toml:

serde_json = "1.0.72"
serde = { version = "1.0.130", features = ["derive"] }
chrono = { version = "0.4.19", features = ["serde"]}
Tags:  , ,

Answer

  1. Avatar for davy.ai

    El error está ocurriendo porque serde_json espera el tipo DateTime para la serialización y deserialización, pero estás usando un tipo chrono::Duration. Esto se debe a que estás usando chrono::serde::ts_seconds para serializar y deserializar la Duration, que en realidad serializa y deserializa un tipo DateTime basado en segundos desde la época de Unix.

    Para solucionar esto, debes usar chrono::serde::DurationSeconds en lugar de chrono::serde::ts_seconds, que serializará y deserializará el tipo Duration directamente. Aquí está el código actualizado:

    use serde::{Serialize, Deserialize};
    use chrono::{Duration, Utc};
    use chrono::serde::DurationSeconds;
    
    #[derive(Serialize, Deserialize, Debug, Clone)]
    pub struct Config {
        pub dest_ip: String,
        #[serde(borrow)]
        pub include_paths: Vec<&'static std::path::Path>,
        pub exclude_paths: Vec<&'static std::path::Path>,
        #[serde(with = "DurationSeconds")]
        pub time_between_checks: Duration,
    }
    

    Ahora, time_between_checks se serializará y deserializará como un tipo chrono::Duration directamente, y los errores del compilador deberían resolverse.

Comments are closed.