-
I want to make the following deserialization work: #[derive(Deserialize, Default, PartialEq, Debug)]
struct Foo {
name: String,
value: u32,
}
impl FromStr for Foo {...}
let data = r#"[
{ "name": "test1", "value": 1 },
"test2"
]"#;
let values: Vec<Foo> = serde_json::from_str(data).unwrap();
assert_eq!(values, vec![
Foo { name: "test1".to_string(), value: 1 },
Foo { name: "test2".to_string(), value: 0 },
]); In serialized data, Ideally, I'd like this, but I don't think that's possible right now: #[serde_as(as = "PickFirst<(_, DisplayFromStr)>")]
#[derive(Deserialize, Default, PartialEq, Debug)]
struct Foo {
name: String,
value: u32,
} Is there any nice way of doing this, apart from using a newtype? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
This is not possible, due to a couple of reasons. First, serde itself does not provide a way to redefine the derived implementations like this. There is no If you do not use the derived #[derive(Deserialize, Default, PartialEq, Debug)]
#[serde(remote = "Self")]
struct Foo {
name: String,
value: u32,
}
impl<'de> Deserialize<'de> for Foo {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct StringOrStruct;
impl<'de> Visitor<'de> for StringOrStruct {
type Value = Foo;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string or map")
}
fn visit_str<E>(self, value: &str) -> Result<Foo, E>
where
E: Error,
{
Ok(FromStr::from_str(value).unwrap())
}
fn visit_map<M>(self, map: M) -> Result<Foo, M::Error>
where
M: MapAccess<'de>,
{
Foo::deserialize(serde::de::value::MapAccessDeserializer::new(map))
}
}
deserializer.deserialize_any(StringOrStruct)
}
} |
Beta Was this translation helpful? Give feedback.
This is not possible, due to a couple of reasons. First, serde itself does not provide a way to redefine the derived implementations like this. There is no
serde(with="")
that you can put on a container.Further, the logic here is circular. To deserialize a
Foo
you first try to deserialize aFoo
, for that you first try to deserialize aFoo
, etc. The inner deserializations will use the same trait implementation.If you do not use the derived
Deserialize
implementation you can achieve what you want. Based on the serde string or struct example: