mirror of
https://github.com/serde-rs/json.git
synced 2025-10-03 07:46:05 +00:00
Allow map key to be borrowed from &Value
This commit is contained in:
parent
62f40665f0
commit
bcad4a9460
101
src/value/de.rs
101
src/value/de.rs
@ -1253,7 +1253,7 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.key.into_deserializer().deserialize_any(visitor)
|
||||
BorrowedCowStrDeserializer::new(self.key).deserialize_any(visitor)
|
||||
}
|
||||
|
||||
deserialize_integer_key!(deserialize_i8 => visit_i8);
|
||||
@ -1387,3 +1387,102 @@ impl Value {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct BorrowedCowStrDeserializer<'de> {
|
||||
value: Cow<'de, str>,
|
||||
}
|
||||
|
||||
impl<'de> BorrowedCowStrDeserializer<'de> {
|
||||
fn new(value: Cow<'de, str>) -> Self {
|
||||
BorrowedCowStrDeserializer { value: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::Deserializer<'de> for BorrowedCowStrDeserializer<'de> {
|
||||
type Error = Error;
|
||||
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
match self.value {
|
||||
Cow::Borrowed(string) => visitor.visit_borrowed_str(string),
|
||||
Cow::Owned(string) => visitor.visit_string(string),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(
|
||||
self,
|
||||
_name: &str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
visitor.visit_enum(self)
|
||||
}
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
|
||||
bytes byte_buf option unit unit_struct newtype_struct seq tuple
|
||||
tuple_struct map struct identifier ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::EnumAccess<'de> for BorrowedCowStrDeserializer<'de> {
|
||||
type Error = Error;
|
||||
type Variant = UnitOnly;
|
||||
|
||||
fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
let value = seed.deserialize(self)?;
|
||||
Ok((value, UnitOnly))
|
||||
}
|
||||
}
|
||||
|
||||
struct UnitOnly;
|
||||
|
||||
impl<'de> de::VariantAccess<'de> for UnitOnly {
|
||||
type Error = Error;
|
||||
|
||||
fn unit_variant(self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
Err(de::Error::invalid_type(
|
||||
Unexpected::UnitVariant,
|
||||
&"newtype variant",
|
||||
))
|
||||
}
|
||||
|
||||
fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
Err(de::Error::invalid_type(
|
||||
Unexpected::UnitVariant,
|
||||
&"tuple variant",
|
||||
))
|
||||
}
|
||||
|
||||
fn struct_variant<V>(
|
||||
self,
|
||||
_fields: &'static [&'static str],
|
||||
_visitor: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
Err(de::Error::invalid_type(
|
||||
Unexpected::UnitVariant,
|
||||
&"struct variant",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -2132,3 +2132,28 @@ fn test_boxed_raw_value() {
|
||||
let array_to_string = serde_json::to_string(&array_from_str).unwrap();
|
||||
assert_eq!(r#"["a",42,{"foo": "bar"},null]"#, array_to_string);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_borrow_in_map_key() {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Outer {
|
||||
map: BTreeMap<MyMapKey, ()>,
|
||||
}
|
||||
|
||||
#[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
|
||||
struct MyMapKey(usize);
|
||||
|
||||
impl<'de> Deserialize<'de> for MyMapKey {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
let s = <&str>::deserialize(deserializer)?;
|
||||
let n = s.parse().map_err(de::Error::custom)?;
|
||||
Ok(MyMapKey(n))
|
||||
}
|
||||
}
|
||||
|
||||
let value = json!({ "map": { "1": null } });
|
||||
Outer::deserialize(&value).unwrap();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user