From 3d0ba9c2cbc9699cf0b24cfe2ae74eb1b3732c76 Mon Sep 17 00:00:00 2001 From: Stefan Bossbaly Date: Mon, 27 May 2024 23:07:07 -0400 Subject: [PATCH] Fixed zip code error Looks like Amtrak API can't make up their mind. They mostly serialize the zip code as a String but for an unknown zip code (why is it unknown?) they will just use the integer type and serialize a 0. I will handle this more elegantly in the future but this will do for now. --- src/responses.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/responses.rs b/src/responses.rs index e5b8ac5..822629a 100644 --- a/src/responses.rs +++ b/src/responses.rs @@ -70,6 +70,50 @@ impl<'de> de::Visitor<'de> for TrainResponseWrapperVisitor { } } +/// Custom visitor used to deserialize the [`zip`] field in the [`Station`] struct. +/// +/// The Amtrak API will sometimes serialize the zip code as an integer and +/// sometimes as a string. This visitor will handle both cases. +/// +/// [`zip`]: Station::zip +struct ZipCodeVisitor; + +impl<'de> de::Visitor<'de> for ZipCodeVisitor { + type Value = String; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string or an integer") + } + + fn visit_str(self, v: &str) -> Result + where + E: de::Error, + { + Ok(v.to_string()) + } + + fn visit_i64(self, v: i64) -> Result + where + E: de::Error, + { + Ok(v.to_string()) + } + + fn visit_u64(self, v: u64) -> Result + where + E: de::Error, + { + Ok(v.to_string()) + } +} + +fn deserialize_zip_code<'de, D>(deserializer: D) -> Result +where + D: de::Deserializer<'de>, +{ + deserializer.deserialize_any(ZipCodeVisitor) +} + /// Represents an Amtrak train #[derive(Debug, Deserialize, Clone)] pub struct Train { @@ -529,6 +573,7 @@ pub struct Station { /// * `19104` /// * `10001` /// * `L7T 4A8` (Canadian zip code) + #[serde(deserialize_with = "deserialize_zip_code")] pub zip: String, /// A list of current [`train_id`] that have departed from or are enroute to