¿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.
davy.ai
Para deserializar de camel case a snake case para la fuente X, se puede utilizar la función
from_reader
de la cajaserde_json
con unDeserializer
personalizado que establece el atributorename_all
en"snake_case"
.Para dejar los datos en snake case al leer o escribir en la fuente Y, se puede utilizar las funciones
from_reader
yto_writer
de la cajaserde_yaml
con unDeserializer
ySerializer
personalizados que establecen el atributorename_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,>