serde
serde copied to clipboard
Serializing fields from a getter method.
Is there any way to serialize a struct field using a getter method?
#[derive(Serialize)]
struct MyStruct {
#[serde(serialize_getter(get_value_with_prefix))]
value: String,
}
impl MyStruct {
fn get_value_with_prefix(&self) -> String {
format!("prefix-{}", self.value)
}
}
I have found this workaround to write a custom serializer
impl Serialize for MyStruct {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("MyStruct", 1)?;
state.serialize_field("value", &self.get_value_with_prefix())?;
state.end()
}
}
But the problem is that I lost the functionality of other field attributes such as:
#[serde(skip_serializing_if = "Option::is_none")]
Is there any other approach to achieve this but still can use the other field attributes?
Have you tried wrapping that field in its own struct and implementing Serialize on that instead, or do you need to use those attributes on the same field?
Attribute #[serde(getter = "...")] already exist but it can be used only with #[serde(remote = "...")] on the type. I think, that this restriction can be eliminated
As a workaround, you can use #[serde(remote = "Self")]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=21178bb66886241df7c505f95152f6b4
This feature request is a special case of #271 where the extra field has the same name as one of the existing fields in the data structure.
I think my preference is the same as #271 (and #760), to leave this in the domain of handwritten Serialize impls. Serialize impls are generally pretty approachable compared to Deserialize impls, and I don't feel the need to expose more attribute-based customization of them through the derive macro.
I agree, and our docs already suggest writing a custom impl if the existing attributes do not serve your purpose
As I already noted, I see no rational reasons why this cannot be implemented. The derive code already exists and everything that is needed to make getter works is to remove if. The generic lib, such as serde, should solve problems instead of creating them and I do not understand why you think the opposite.
(Also, closing this issue with the "completed" resolution does not reflect the current status of things).
It isn't a design goal for derive to be able to express a larger diversity of serde trait impls. Derive is a good fit when the behavior of a trait impl closely corresponds with the structure of a data structure. We expose attributes to tweak the correspondence between behavior and data structure in moderate ways, but when behavior and data structure diverge more, "programming in attributes" starts to be a larger obfuscation than just writing Rust code.
All these considerations would apply if the requested attribute did not exist and some code had to be written to support it. But it already is! Why don't your considerations apply in the case of remote types? There, too, you can just write the impl by hand. So far, this limitation looks like "just because".