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.

¿Se puede especificar la regla rename_all de serde en tiempo de ejecución?

Tengo un modelo de datos que me gustaría deserializar de "camelCase" al estándar rust "snake_case" al leer de una fuente, X. Pero me gustaría dejarlo en "snake_case" al leer o escribir en otra fuente, Y.

Por ejemplo, el siguiente código,

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Data {
  foo_bar: String,
  hello_world: String,
}

sólo puede ser codificado y decodificado en camel case. Incluso si defino manualmente mis implementaciones de Serialize y Deserialize, no puedo definir múltiples para la misma estructura. Podría definir una segunda estructura que sea una copia/pegado de la otra y luego derivar, pero ese método se volvería tedioso con múltiples estructuras grandes. Lo que realmente me gustaría hacer es especificar ese atributo de rename_all en tiempo de ejecución. Pero no veo ninguna manera de hacerlo en la API de serde.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para deserializar de camel case a snake case para la fuente X, se puede utilizar la función from_reader de la caja serde_json con un Deserializer personalizado que establece el atributo rename_all en "snake_case".

    use serde::Deserialize;
    use serde_json::{self, Deserializer};
    use std::fs::File;
    
    #[derive(Deserialize)]
    struct Data {
        foo_bar: String,
        hello_word: String,
    }
    
    fn deserialize_from_file_x(file_path: &str) -> Result<data, serde_json::error=""> {
        let file = File::open(file_path)?;
        let deserializer = Deserializer::from_reader(file).with_name_map(serde_json::from_str(r#"{ "style": "snake_case" }"#))?;
        let data = Data::deserialize(deserializer)?;
        Ok(data)
    }
    

    Para dejar los datos en snake case al leer o escribir en la fuente Y, se puede utilizar las funciones from_reader y to_writer de la caja serde_yaml con un Deserializer y Serializer personalizados que establecen el atributo rename_all en "snake_case".

    “`rust
    use serde::{Deserialize, Serialize};
    use serde_yaml::{self, Deserializer, Serializer};
    use std::fs::File;

    #[derive(Serialize, Deserialize)]
    #[serde(rename_all = “snake_case”)]
    struct Data {
    foo_bar: String,
    hello_word: String,
    }

    fn deserialize_from_file_y(file_path: &str) -> Result<data, serde_yaml::error=””> {
    let file = File::open(file_path)?;
    let deserializer = Deserializer::from_reader(file).with_name_map(serde_yaml::from_str(r#”{ rename_all: “snake_case” }”#))?;
    let data = Data::deserialize(deserializer)?;
    Ok(data)
    }

    fn serialize_to_file_y(file_path: &str, data: &Data) -> Result<(), serde_yaml::Error> {
    let file = File::create(file_path)?;
    let mut serializer = Serializer::new(file).with_indentation(2);
    serializer.serialize_map(Some(2))?;
    serializer.serialize_entry(“rename_all”, “snake_case”)?;
    data.serialize(&mut serializer)?;
    serializer.serialize_map(None)?;
    Ok(())
    }
    “`</data,></data,>

Comments are closed.