mirror of https://github.com/fafhrd91/actix-web
parse numeric values as well
This commit is contained in:
parent
7169f54d3b
commit
9c453c0786
|
|
@ -3,6 +3,9 @@
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.88.
|
- Minimum supported Rust version (MSRV) is now 1.88.
|
||||||
|
- Support `deserialize_any` in `PathDeserializer` (enables derived `#[serde(untagged)]` enums in path segments). [#2881]
|
||||||
|
|
||||||
|
[#2881]: https://github.com/actix/actix-web/pull/2881
|
||||||
|
|
||||||
## 0.5.3
|
## 0.5.3
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ impl<'de, T: ResourcePath + 'de> Deserializer<'de> for PathDeserializer<'de, T>
|
||||||
unsupported_type!(deserialize_identifier, "identifier");
|
unsupported_type!(deserialize_identifier, "identifier");
|
||||||
unsupported_type!(deserialize_ignored_any, "ignored_any");
|
unsupported_type!(deserialize_ignored_any, "ignored_any");
|
||||||
|
|
||||||
parse_single_value!(deserialize_any, deserialize_str);
|
parse_single_value!(deserialize_any);
|
||||||
parse_single_value!(deserialize_bool);
|
parse_single_value!(deserialize_bool);
|
||||||
parse_single_value!(deserialize_i8);
|
parse_single_value!(deserialize_i8);
|
||||||
parse_single_value!(deserialize_i16);
|
parse_single_value!(deserialize_i16);
|
||||||
|
|
@ -430,11 +430,37 @@ impl<'de> Deserializer<'de> for Value<'de> {
|
||||||
Err(de::value::Error::custom("unsupported type: tuple struct"))
|
Err(de::value::Error::custom("unsupported type: tuple struct"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_any<V>(self, v: V) -> Result<V::Value, Self::Error>
|
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
self.deserialize_str(v)
|
let decoded = FULL_QUOTER
|
||||||
|
.with(|q| q.requote_str_lossy(self.value))
|
||||||
|
.map(Cow::Owned)
|
||||||
|
.unwrap_or(Cow::Borrowed(self.value));
|
||||||
|
|
||||||
|
let s = decoded.as_ref();
|
||||||
|
// We have to do it manually here on behalf of serde.
|
||||||
|
if let Ok(v) = s.parse::<u64>() {
|
||||||
|
if let Ok(v) = u32::try_from(v) {
|
||||||
|
return visitor.visit_u32(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visitor.visit_u64(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(v) = s.parse::<i64>() {
|
||||||
|
if let Ok(v) = i32::try_from(v) {
|
||||||
|
return visitor.visit_i32(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return visitor.visit_i64(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
match decoded {
|
||||||
|
Cow::Borrowed(value) => visitor.visit_borrowed_str(value),
|
||||||
|
Cow::Owned(value) => visitor.visit_string(value),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsupported_type!(deserialize_seq, "seq");
|
unsupported_type!(deserialize_seq, "seq");
|
||||||
|
|
@ -731,10 +757,7 @@ mod tests {
|
||||||
impl<'de> Visitor<'de> for Vis {
|
impl<'de> Visitor<'de> for Vis {
|
||||||
type Value = AnyEnumCustom;
|
type Value = AnyEnumCustom;
|
||||||
|
|
||||||
fn expecting<'a>(
|
fn expecting<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result {
|
||||||
&self,
|
|
||||||
f: &mut std::fmt::Formatter<'a>,
|
|
||||||
) -> std::fmt::Result {
|
|
||||||
write!(f, "my thing")
|
write!(f, "my thing")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -745,6 +768,26 @@ mod tests {
|
||||||
Ok(AnyEnumCustom::Int(v))
|
Ok(AnyEnumCustom::Int(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
match u32::try_from(v) {
|
||||||
|
Ok(v) => Ok(AnyEnumCustom::Int(v)),
|
||||||
|
Err(_) => Ok(AnyEnumCustom::String(format!("some str: {v}"))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
match u32::try_from(v) {
|
||||||
|
Ok(v) => Ok(AnyEnumCustom::Int(v)),
|
||||||
|
Err(_) => Ok(AnyEnumCustom::String(format!("some str: {v}"))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
|
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
|
||||||
v.parse().map(AnyEnumCustom::Int).or_else(|_| {
|
v.parse().map(AnyEnumCustom::Int).or_else(|_| {
|
||||||
Ok(match v {
|
Ok(match v {
|
||||||
|
|
@ -788,11 +831,9 @@ mod tests {
|
||||||
let mut path = Path::new("/other/123");
|
let mut path = Path::new("/other/123");
|
||||||
rdef.capture_match_info(&mut path);
|
rdef.capture_match_info(&mut path);
|
||||||
let de = PathDeserializer::new(&path);
|
let de = PathDeserializer::new(&path);
|
||||||
let segment: (AnyEnumCustom, AnyEnumDerive) =
|
let segment: (AnyEnumCustom, AnyEnumDerive) = serde::Deserialize::deserialize(de).unwrap();
|
||||||
serde::Deserialize::deserialize(de).unwrap();
|
|
||||||
assert_eq!(segment.0, AnyEnumCustom::Other);
|
assert_eq!(segment.0, AnyEnumCustom::Other);
|
||||||
// Deserializes to `String` instead of `Int` because deserializing defaults to `str` and serde doesn't automatically implement parsing numbers from `&str`s
|
assert_eq!(segment.1, AnyEnumDerive::Int(123));
|
||||||
assert_eq!(segment.1, AnyEnumDerive::String("123".to_string()));
|
|
||||||
|
|
||||||
// map
|
// map
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue