Riven
Riven copied to clipboard
How to serialize PlatformRoute, Tier, Division, etc?
Some structures like Match
derive serde::Serialize
and serde::Deserialize
for parsing purpose but a few enums don't. Is there a reason?
For example, I would like to create a serializable structure like this:
#[derive(Serialize, Deserialize)]
pub struct config {
pub version: String,
pub servers: Vec<PlatformRoute>,
pub tiers: Vec<Tier>
}
To answer, anything that shows up in JSON responses returned by the API derive serde (though I guess only the de
is needed), and things like PlatformRoute
don't since they don't show up in the JSON.
Tier
and Division
actually do implement serde manually (not derive) since they're serialized as strings rather than numbers in the JSON.
The easiest way to deal with this in current form would be with a newtype and serde impl, something like this: (untested)
pub struct PlatformRouteSerde(pub PlatformRoute);
impl<'de> serde::de::Deserialize<'de> for PlatformRouteSerde {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::de::Deserializer<'de>
{
let num = u8::deserialize(deserializer)?;
let route = num.parse().map_err(serde::de::Error::custom)?;
PlatformRouteSerde(route)
}
}
impl serde::ser::Serialize for PlatformRouteSerde {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
serializer.serialize_u8(self.0.into())
}
}
Thanks, I just saw the serde_string
macro. Regarding Tier
and Division
I feel the macro is redundant: #derive(serde::Serialize)
does stringify the enum variant by default (while #derive(serde_repr::Serialize_repr)
would use the repr
value instead). For example:
use serde_repr::{Serialize_repr, Deserialize_repr};
use serde::{Serialize, Deserialize};
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)]
#[repr(u8)]
enum SmallPrimeRepr {
Two = 2,
Three = 3,
Five = 5,
Seven = 7,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[repr(u8)]
enum SmallPrime {
Two = 2,
Three = 3,
Five = 5,
Seven = 7,
}
fn main() -> serde_json::Result<()> {
let j_repr = serde_json::to_string(&SmallPrimeRepr::Seven)?;
let j = serde_json::to_string(&SmallPrime::Seven)?;
println!("{} {}", j_repr, j);
let p_repr: SmallPrimeRepr = serde_json::from_str("2")?;
let p: SmallPrime = serde_json::from_str("\"Two\"")?;
println!("{:?} {:?}", p_repr, p);
Ok(())
}
prints:
7 "Seven"
Two Two
So I think for Tier
/Division
a simple #derive(serde::Serialize)
would do. For PlatformRoute
I guess it is not that easy because then there is the issue with serde
<-> strum
serialization consistency =/