//! [`serde_json::Value`] but uses RawValue internally //! //! This code forks from the serde_json code, but replaces internal Value with RawValue where possible. //! //! Taken from //! Licensed from serde-rs under MIT or APACHE-2.0, with modifications by Conrad Ludgate use core::fmt; use std::borrow::Cow; use serde::{ de::{IgnoredAny, MapAccess, SeqAccess, Visitor}, Deserialize, }; use serde_json::value::RawValue; pub enum LazyValue<'de> { Null, Bool, Number, String(Cow<'de, str>), Array(Vec<&'de RawValue>), Object, } impl<'de> Deserialize<'de> for LazyValue<'de> { #[inline] fn deserialize(deserializer: D) -> Result, D::Error> where D: serde::Deserializer<'de>, { struct ValueVisitor; impl<'de> Visitor<'de> for ValueVisitor { type Value = LazyValue<'de>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("any valid JSON value") } #[inline] fn visit_bool(self, _value: bool) -> Result, E> { Ok(LazyValue::Bool) } #[inline] fn visit_i64(self, _value: i64) -> Result, E> { Ok(LazyValue::Number) } #[inline] fn visit_u64(self, _value: u64) -> Result, E> { Ok(LazyValue::Number) } #[inline] fn visit_f64(self, _value: f64) -> Result, E> { Ok(LazyValue::Number) } #[inline] fn visit_str(self, value: &str) -> Result, E> where E: serde::de::Error, { self.visit_string(String::from(value)) } #[inline] fn visit_borrowed_str(self, value: &'de str) -> Result, E> where E: serde::de::Error, { Ok(LazyValue::String(Cow::Borrowed(value))) } #[inline] fn visit_string(self, value: String) -> Result, E> { Ok(LazyValue::String(Cow::Owned(value))) } #[inline] fn visit_none(self) -> Result, E> { Ok(LazyValue::Null) } #[inline] fn visit_some(self, deserializer: D) -> Result, D::Error> where D: serde::Deserializer<'de>, { Deserialize::deserialize(deserializer) } #[inline] fn visit_unit(self) -> Result, E> { Ok(LazyValue::Null) } #[inline] fn visit_seq(self, mut visitor: V) -> Result, V::Error> where V: SeqAccess<'de>, { let mut vec = Vec::new(); while let Some(elem) = visitor.next_element()? { vec.push(elem); } Ok(LazyValue::Array(vec)) } fn visit_map(self, mut visitor: V) -> Result, V::Error> where V: MapAccess<'de>, { while visitor.next_entry::()?.is_some() {} Ok(LazyValue::Object) } } deserializer.deserialize_any(ValueVisitor) } } #[cfg(test)] mod tests { use std::borrow::Cow; use typed_json::json; use super::LazyValue; #[test] fn object() { let json = json! {{ "foo": { "bar": 1 }, "baz": [2, 3], }} .to_string(); let lazy: LazyValue = serde_json::from_str(&json).unwrap(); let LazyValue::Object = lazy else { panic!("expected object") }; } #[test] fn array() { let json = json! {[ { "bar": 1 }, [2, 3], ]} .to_string(); let lazy: LazyValue = serde_json::from_str(&json).unwrap(); let LazyValue::Array(array) = lazy else { panic!("expected array") }; assert_eq!(array.len(), 2); assert_eq!(array[0].get(), r#"{"bar":1}"#); assert_eq!(array[1].get(), r#"[2,3]"#); } #[test] fn string() { let json = json! { "hello world" }.to_string(); let lazy: LazyValue = serde_json::from_str(&json).unwrap(); let LazyValue::String(Cow::Borrowed(string)) = lazy else { panic!("expected borrowed string") }; assert_eq!(string, "hello world"); let json = json! { "hello \n world" }.to_string(); let lazy: LazyValue = serde_json::from_str(&json).unwrap(); let LazyValue::String(Cow::Owned(string)) = lazy else { panic!("expected owned string") }; assert_eq!(string, "hello \n world"); } }