Skip to content

Commit a8a45f7

Browse files
authored
Merge pull request #74 from mstyura/deserialize-numbers-from-string
Deserialize numbers from string
2 parents 566f7cb + 5e112ec commit a8a45f7

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

src/api.rs

+30
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub enum ConstraintExpression {
6363
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
6464
pub struct Variant {
6565
pub name: String,
66+
#[serde(deserialize_with = "deserialize_number_from_string")]
6667
pub weight: u16,
6768
pub payload: Option<HashMap<String, String>>,
6869
pub overrides: Option<Vec<VariantOverride>>,
@@ -137,6 +138,25 @@ pub struct MetricsBucket {
137138
pub toggles: HashMap<String, ToggleMetrics>,
138139
}
139140

141+
fn deserialize_number_from_string<'de, T, D>(deserializer: D) -> Result<T, D::Error>
142+
where
143+
D: serde::Deserializer<'de>,
144+
T: std::str::FromStr + serde::Deserialize<'de>,
145+
<T as std::str::FromStr>::Err: std::fmt::Display,
146+
{
147+
#[derive(Deserialize)]
148+
#[serde(untagged)]
149+
enum StringOrInt<T> {
150+
String(String),
151+
Number(T),
152+
}
153+
154+
match StringOrInt::<T>::deserialize(deserializer)? {
155+
StringOrInt::String(s) => s.parse::<T>().map_err(serde::de::Error::custom),
156+
StringOrInt::Number(i) => Ok(i),
157+
}
158+
}
159+
140160
#[cfg(test)]
141161
mod tests {
142162
use super::Registration;
@@ -249,6 +269,16 @@ mod tests {
249269
Ok(())
250270
}
251271

272+
#[test]
273+
fn test_parse_variant_with_str_weight() -> Result<(), serde_json::Error> {
274+
let data = r#"
275+
{"name":"Foo","weight":"50","payload":{"type":"string","value":"bar"}}
276+
"#;
277+
let parsed: super::Variant = serde_json::from_str(data)?;
278+
assert_eq!(50, parsed.weight);
279+
Ok(())
280+
}
281+
252282
#[test]
253283
fn test_registration_customisation() {
254284
Registration {

0 commit comments

Comments
 (0)