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 deserializar un campo de cadena a bool.

Actualmente tengo una cadena JSON que estoy deserializando con serde_json.

{
  "foo": "<val>" // val puede contener "SI" o "NO"
}

Me gustaría deserializar esto a un valor bool utilizando serde y una búsqueda personalizada que convierta “SI” -> verdadero y viceversa.

#[derive(Deserialize)]
pub struct Entry {
   pub foo: bool, // ¿Cómo puedo expresar la deserialización de cadenas a booleanos?
}

¿Cómo puedo hacer eso de manera simple?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Una forma de lograr esto es implementando una deserialización personalizada para el tipo bool en serde.

    Primero, define una enumeración de BoolString personalizada que represente las dos posibles cadenas de texto:

    enum BoolString {
        Yes,
        No,
    }
    

    Luego, implementa el rasgo serde::Deserialize para BoolString:

    impl<'de> Deserialize<'de> for BoolString {
        fn deserialize<d>(deserializer: D) -> Result<self, d::error="">
        where
            D: Deserializer<'de>,
        {
            let s = String::deserialize(deserializer)?;
            match s.as_str() {
                "SI" => Ok(BoolString::Yes),
                "NO" => Ok(BoolString::No),
                _ => Err(D::Error::invalid_value(
                    de::Unexpected::Str(&s),
                    &"SI o NO",
                )),
            }
        }
    }
    

    Esta implementación deserializa una cadena de texto y la convierte en una variante de enumeración, devolviendo un error si la cadena de texto no es uno de los dos valores esperados.

    A continuación, implementa serde::Deserialize para la estructura Entry, usando el atributo #[serde(with = "BoolString")] para indicar que el campo foo debe ser deserializado usando la enumeración personalizada BoolString:

    #[derive(Deserialize)]
    pub struct Entry {
        #[serde(with = "BoolString")]
        pub foo: bool,
    }
    

    Ahora puedes deserializar la cadena JSON a una instancia de Entry usando serde_json:

    let json = r#"{"foo": "SI"}"#;
    let entry: Entry = serde_json::from_str(json)?;
    

    El campo entry.foo será true en este ejemplo.

    let json = r#"{"foo": "NO"}"#;
    let entry: Entry = serde_json::from_str(json)?;
    

    El campo entry.foo será false en este ejemplo.</self,>

Comments are closed.