Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weird behaviour when deserializing a RawValue through a Visitor. #1150

Open
aatifsyed opened this issue Jul 1, 2024 · 1 comment
Open

Weird behaviour when deserializing a RawValue through a Visitor. #1150

aatifsyed opened this issue Jul 1, 2024 · 1 comment

Comments

@aatifsyed
Copy link

In a variation of the StringOrStruct example in the docs, I'm writing the following "filter" for deserializers:

#[derive(Debug)]
struct MapOrSequence<T>(T);
impl<'de, T: Deserialize<'de>> Deserialize<'de> for MapOrSequence<T> {
    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        Ok(Self(deserializer.deserialize_any(Visitor(PhantomData))?))
    }
}

struct Visitor<T>(PhantomData<fn() -> T>);
impl<'de, T: Deserialize<'de>> serde::de::Visitor<'de> for Visitor<T> {
    type Value = T;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a map or a sequence")
    }
    fn visit_map<A: serde::de::MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> {
        T::deserialize(serde::de::value::MapAccessDeserializer::new(map))
    }
    fn visit_seq<A: serde::de::SeqAccess<'de>>(self, seq: A) -> Result<Self::Value, A::Error> {
        T::deserialize(serde::de::value::SeqAccessDeserializer::new(seq))
    }
}

It works as expected when wrapping a serde_json::Value

serde_json::from_value::<MapOrSequence<Value>>(json!(null)).unwrap_err();
serde_json::from_value::<MapOrSequence<Value>>(json!(1)).unwrap_err();
serde_json::from_value::<MapOrSequence<Value>>(json!("s")).unwrap_err();

serde_json::from_value::<MapOrSequence<Value>>(json!({})).unwrap();
serde_json::from_value::<MapOrSequence<Value>>(json!([])).unwrap();

But I get false negatives when using serde_json::value::RawValue:

serde_json::from_value::<MapOrSequence<Box<RawValue>>>(json!(null)).unwrap_err();
serde_json::from_value::<MapOrSequence<Box<RawValue>>>(json!(1)).unwrap_err();
serde_json::from_value::<MapOrSequence<Box<RawValue>>>(json!("s")).unwrap_err();

serde_json::from_value::<MapOrSequence<Box<RawValue>>>(json!({})).unwrap(); // boom
serde_json::from_value::<MapOrSequence<Box<RawValue>>>(json!([])).unwrap(); // boom

The error messages are a little odd:

called `Result::unwrap()` on an `Err` value: Error("invalid type: map, expected any valid JSON value", line: 0, column: 0)
called `Result::unwrap()` on an `Err` value: Error("invalid type: sequence, expected any valid JSON value", line: 0, column: 0)

full example on playground

I can't tell if my Visitor is bugged, but I think I assumed that if it worked for Value it should work for RawValue.

We fall over at line 355:

json/src/raw.rs

Lines 340 to 359 in b48b9a3

struct BoxedVisitor;
impl<'de> Visitor<'de> for BoxedVisitor {
type Value = Box<RawValue>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "any valid JSON value")
}
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: MapAccess<'de>,
{
let value = tri!(visitor.next_key::<RawKey>());
if value.is_none() {
return Err(de::Error::invalid_type(Unexpected::Map, &self));
}
visitor.next_value_seed(BoxedFromString)
}
}

@aatifsyed
Copy link
Author

aatifsyed commented Jul 1, 2024

In fact, going through a simple passthrough visitor fails
use serde::{de::value::*, Deserialize};
#[cfg(test)]
use serde_json::{json, value::RawValue, Value};
use std::marker::PhantomData;

#[derive(Debug)]
struct Passthrough<T>(T);
impl<'de, T: Deserialize<'de>> Deserialize<'de> for Passthrough<T> {
    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        Ok(Self(deserializer.deserialize_any(Visitor(PhantomData))?))
    }
}

struct Visitor<T>(PhantomData<fn() -> T>);

impl<'de, T> serde::de::Visitor<'de> for Visitor<T>
where
    T: Deserialize<'de>,
{
    type Value = T;

    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        formatter.write_str("AAAAA")
    }
    fn visit_bool<E: serde::de::Error>(self, v: bool) -> Result<Self::Value, E> {
        T::deserialize(BoolDeserializer::new(v))
    }
    fn visit_i8<E: serde::de::Error>(self, v: i8) -> Result<Self::Value, E> {
        T::deserialize(I8Deserializer::new(v))
    }
    fn visit_i16<E: serde::de::Error>(self, v: i16) -> Result<Self::Value, E> {
        T::deserialize(I16Deserializer::new(v))
    }
    fn visit_i32<E: serde::de::Error>(self, v: i32) -> Result<Self::Value, E> {
        T::deserialize(I32Deserializer::new(v))
    }
    fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<Self::Value, E> {
        T::deserialize(I64Deserializer::new(v))
    }
    fn visit_i128<E: serde::de::Error>(self, v: i128) -> Result<Self::Value, E> {
        T::deserialize(I128Deserializer::new(v))
    }
    fn visit_u8<E: serde::de::Error>(self, v: u8) -> Result<Self::Value, E> {
        T::deserialize(U8Deserializer::new(v))
    }
    fn visit_u16<E: serde::de::Error>(self, v: u16) -> Result<Self::Value, E> {
        T::deserialize(U16Deserializer::new(v))
    }
    fn visit_u32<E: serde::de::Error>(self, v: u32) -> Result<Self::Value, E> {
        T::deserialize(U32Deserializer::new(v))
    }
    fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<Self::Value, E> {
        T::deserialize(U64Deserializer::new(v))
    }
    fn visit_u128<E: serde::de::Error>(self, v: u128) -> Result<Self::Value, E> {
        T::deserialize(U128Deserializer::new(v))
    }
    fn visit_f32<E: serde::de::Error>(self, v: f32) -> Result<Self::Value, E> {
        T::deserialize(F32Deserializer::new(v))
    }
    fn visit_f64<E: serde::de::Error>(self, v: f64) -> Result<Self::Value, E> {
        T::deserialize(F64Deserializer::new(v))
    }
    fn visit_char<E: serde::de::Error>(self, v: char) -> Result<Self::Value, E> {
        T::deserialize(CharDeserializer::new(v))
    }
    fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
        T::deserialize(StrDeserializer::new(v))
    }
    fn visit_borrowed_str<E: serde::de::Error>(self, v: &'de str) -> Result<Self::Value, E> {
        T::deserialize(BorrowedStrDeserializer::new(v))
    }
    fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Self::Value, E> {
        T::deserialize(StringDeserializer::new(v))
    }
    fn visit_bytes<E: serde::de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
        T::deserialize(BytesDeserializer::new(v))
    }
    fn visit_borrowed_bytes<E: serde::de::Error>(self, v: &'de [u8]) -> Result<Self::Value, E> {
        T::deserialize(BorrowedBytesDeserializer::new(v))
    }
    fn visit_byte_buf<E: serde::de::Error>(self, v: Vec<u8>) -> Result<Self::Value, E> {
        T::deserialize(BytesDeserializer::new(&v))
    }
    fn visit_none<E: serde::de::Error>(self) -> Result<Self::Value, E> {
        T::deserialize(UnitDeserializer::new())
    }
    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        T::deserialize(deserializer)
    }
    fn visit_unit<E: serde::de::Error>(self) -> Result<Self::Value, E> {
        T::deserialize(UnitDeserializer::new())
    }
    fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        T::deserialize(deserializer)
    }
    fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
    where
        A: serde::de::SeqAccess<'de>,
    {
        T::deserialize(SeqAccessDeserializer::new(seq))
    }
    fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
    where
        A: serde::de::MapAccess<'de>,
    {
        T::deserialize(MapAccessDeserializer::new(map))
    }
    fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
    where
        A: serde::de::EnumAccess<'de>,
    {
        T::deserialize(EnumAccessDeserializer::new(data))
    }
}

#[test]
fn wrapped() {
    // normal value

    serde_json::from_value::<Passthrough<Value>>(json!(null)).unwrap();
    serde_json::from_value::<Passthrough<Value>>(json!(1)).unwrap();
    serde_json::from_value::<Passthrough<Value>>(json!("s")).unwrap();

    serde_json::from_value::<Passthrough<Value>>(json!({})).unwrap();
    serde_json::from_value::<Passthrough<Value>>(json!([])).unwrap();

    // raw value

    serde_json::from_value::<Passthrough<Box<RawValue>>>(json!(null)).unwrap(); // boom
    serde_json::from_value::<Passthrough<Box<RawValue>>>(json!(1)).unwrap(); // boom
    serde_json::from_value::<Passthrough<Box<RawValue>>>(json!("s")).unwrap(); // boom

    serde_json::from_value::<Passthrough<Box<RawValue>>>(json!({})).unwrap(); // boom
    serde_json::from_value::<Passthrough<Box<RawValue>>>(json!([])).unwrap(); // boom
}

on playground

@aatifsyed aatifsyed changed the title Weird behaviour when serializing a RawValue through a Visitor. Weird behaviour when deserializing a RawValue through a Visitor. Jul 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant