Question about flattening struct in place of key of map with Serde

Hello. I have the following structs:

struct Player {
    name: String,
}

struct Agent {
    name: String,
}
#[derive(Serialize)]
struct Match {
    agents: HashMap<Player, Agent>,
}

How can I make serde to flatten the keys and values when serializing/deserializing the Match? For example

Match {
  agents: HashMap::from([(Player { name: "Rb"}, Agent { name: "Killjoy"})])
}

should get serialized into

{ agents: {"Rb": "Killjoy" }}

and same with deserialization.

I have actually achieved the serializing part with implementing my own serializer, but deser seems more complicated, so I wanted to know if there's any easier way to do both.

(FYI: the serializer part is pretty easy:

impl Serialize for Player {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer {
        serializer.serialize_str(&self.name)
    }
}
impl Serialize for Agent {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer {
        serializer.serialize_str(&self.name)
    }
}

)

Not really:

impl<'de> Deserialize<'de> for Player {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>
    {
        let name = String::deserialize(deserializer)?;
        Ok(Player { name })
    }
}

impl<'de> Deserialize<'de> for Agent {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>
    {
        let name = String::deserialize(deserializer)?;
        Ok(Agent { name })
    }
}

Yeah, thanks for this, seems easy enough! I saw visitor and stuff in the example in documentation.

But I actually solved the issue with #[serde(transparent)]. Marking the struct with this is exactly what I needed. Then usual derive just works the way I wanted.

That's only needed if you want to avoid creating an owned value (e.g. you don't want to create a String just to deserialize it into an enum variant and then throw it away). Otherwise, forwarding to other types' Deserialize is entirely possible and easy.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.