serde-rs / json

Strongly typed JSON library for Rust
Apache License 2.0
4.85k stars 555 forks source link

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

Open aatifsyed opened 3 months ago

aatifsyed commented 3 months ago

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: https://github.com/serde-rs/json/blob/b48b9a3a0c09952579e98c8940fe0d1ee4aae588/src/raw.rs#L340-L359

aatifsyed commented 3 months ago
In fact, going through a simple passthrough visitor fails ```rust use serde::{de::value::*, Deserialize}; #[cfg(test)] use serde_json::{json, value::RawValue, Value}; use std::marker::PhantomData; #[derive(Debug)] struct Passthrough(T); impl<'de, T: Deserialize<'de>> Deserialize<'de> for Passthrough { fn deserialize>(deserializer: D) -> Result { Ok(Self(deserializer.deserialize_any(Visitor(PhantomData))?)) } } struct Visitor(PhantomData T>); impl<'de, T> serde::de::Visitor<'de> for Visitor 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(self, v: bool) -> Result { T::deserialize(BoolDeserializer::new(v)) } fn visit_i8(self, v: i8) -> Result { T::deserialize(I8Deserializer::new(v)) } fn visit_i16(self, v: i16) -> Result { T::deserialize(I16Deserializer::new(v)) } fn visit_i32(self, v: i32) -> Result { T::deserialize(I32Deserializer::new(v)) } fn visit_i64(self, v: i64) -> Result { T::deserialize(I64Deserializer::new(v)) } fn visit_i128(self, v: i128) -> Result { T::deserialize(I128Deserializer::new(v)) } fn visit_u8(self, v: u8) -> Result { T::deserialize(U8Deserializer::new(v)) } fn visit_u16(self, v: u16) -> Result { T::deserialize(U16Deserializer::new(v)) } fn visit_u32(self, v: u32) -> Result { T::deserialize(U32Deserializer::new(v)) } fn visit_u64(self, v: u64) -> Result { T::deserialize(U64Deserializer::new(v)) } fn visit_u128(self, v: u128) -> Result { T::deserialize(U128Deserializer::new(v)) } fn visit_f32(self, v: f32) -> Result { T::deserialize(F32Deserializer::new(v)) } fn visit_f64(self, v: f64) -> Result { T::deserialize(F64Deserializer::new(v)) } fn visit_char(self, v: char) -> Result { T::deserialize(CharDeserializer::new(v)) } fn visit_str(self, v: &str) -> Result { T::deserialize(StrDeserializer::new(v)) } fn visit_borrowed_str(self, v: &'de str) -> Result { T::deserialize(BorrowedStrDeserializer::new(v)) } fn visit_string(self, v: String) -> Result { T::deserialize(StringDeserializer::new(v)) } fn visit_bytes(self, v: &[u8]) -> Result { T::deserialize(BytesDeserializer::new(v)) } fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result { T::deserialize(BorrowedBytesDeserializer::new(v)) } fn visit_byte_buf(self, v: Vec) -> Result { T::deserialize(BytesDeserializer::new(&v)) } fn visit_none(self) -> Result { T::deserialize(UnitDeserializer::new()) } fn visit_some(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { T::deserialize(deserializer) } fn visit_unit(self) -> Result { T::deserialize(UnitDeserializer::new()) } fn visit_newtype_struct(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { T::deserialize(deserializer) } fn visit_seq(self, seq: A) -> Result where A: serde::de::SeqAccess<'de>, { T::deserialize(SeqAccessDeserializer::new(seq)) } fn visit_map(self, map: A) -> Result where A: serde::de::MapAccess<'de>, { T::deserialize(MapAccessDeserializer::new(map)) } fn visit_enum(self, data: A) -> Result where A: serde::de::EnumAccess<'de>, { T::deserialize(EnumAccessDeserializer::new(data)) } } #[test] fn wrapped() { // normal value serde_json::from_value::>(json!(null)).unwrap(); serde_json::from_value::>(json!(1)).unwrap(); serde_json::from_value::>(json!("s")).unwrap(); serde_json::from_value::>(json!({})).unwrap(); serde_json::from_value::>(json!([])).unwrap(); // raw value serde_json::from_value::>>(json!(null)).unwrap(); // boom serde_json::from_value::>>(json!(1)).unwrap(); // boom serde_json::from_value::>>(json!("s")).unwrap(); // boom serde_json::from_value::>>(json!({})).unwrap(); // boom serde_json::from_value::>>(json!([])).unwrap(); // boom } ```

on playground