-
Scenario: You're serializing a struct that contains a type from a foreign crate that either doesn't implement Currently, this can be accomplished by defining two different use serde::{Serialize, Serializer};
use serde_with::skip_serializing_none;
struct ForeignType;
#[skip_serializing_none]
#[derive(Serialize)]
struct Data {
#[serde(serialize_with = "serialize_foreign")]
field: ForeignType,
#[serde(serialize_with = "serialize_option_foreign")]
nullable: Option<ForeignType>,
}
fn main() {
let data1 = Data {
field: ForeignType,
nullable: Some(ForeignType),
};
assert_eq!(
serde_json::to_string(&data1).unwrap(),
r#"{"field":"<Foreign type>","nullable":"<Foreign type>"}"#
);
let data2 = Data {
field: ForeignType,
nullable: None,
};
assert_eq!(
serde_json::to_string(&data2).unwrap(),
r#"{"field":"<Foreign type>"}"#
);
println!("OK");
}
fn foreign2string(_: &ForeignType) -> String {
String::from("<Foreign type>")
}
fn serialize_foreign<S: Serializer>(value: &ForeignType, serializer: S) -> Result<S::Ok, S::Error> {
foreign2string(value).serialize(serializer)
}
fn serialize_option_foreign<S: Serializer>(
value: &Option<ForeignType>,
serializer: S,
) -> Result<S::Ok, S::Error> {
value.as_ref().map(foreign2string).serialize(serializer)
} However, I really feel like this sort of scenario would or should be something that #[serde_as]
#[skip_serializing_none]
#[derive(Serialize)]
struct Data {
#[serde(serialize_with = "serialize_foreign")]
field: ForeignType,
#[serde_as(as = "Option<serialize_foreign>")]
nullable: Option<ForeignType>,
} but this doesn't compile. Does |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
This is exactly what The bottom example that you call "abuse" is basically what you have to do, except you can't use a function as a type like this. So you have to use a new type and implement |
Beta Was this translation helpful? Give feedback.
This is exactly what
serde_with
helps with. I don't know why you think that serializing anOption<T>
is a problem. There is even special support to make working withOption
simpler and more intuitive: https://docs.rs/serde_with/3.4.0/serde_with/guide/serde_as/index.html#deserializing-optional-fieldsThe bottom example that you call "abuse" is basically what you have to do, except you can't use a function as a type like this. So you have to use a new type and implement
SerializeAs
, but that is just some boilerplate syntax changes. Check out the user guide for how to implementSerializeAs
. It is very simple since you already have the function: https://docs.rs/serde_with/3.4.0/serde_with/gui…