diff --git a/Cargo.toml b/Cargo.toml index 2f8ebe5ca..0ccec383a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,12 @@ compiletest_rs = "0.3" serde_bytes = "0.10" serde_derive = "1.0" +[package.metadata.docs.rs] +features = ["raw_value"] + +[package.metadata.playground] +features = ["raw_value"] + ### FEATURES ################################################################# @@ -41,3 +47,6 @@ preserve_order = ["indexmap"] # allows JSON numbers of arbitrary size/precision to be read into a Number and # written back to a JSON string without loss of precision. arbitrary_precision = [] + +# Provide a RawValue type that can hold unprocessed JSON during deserialization. +raw_value = [] diff --git a/src/de.rs b/src/de.rs index f1c5c3cff..7e44968e2 100644 --- a/src/de.rs +++ b/src/de.rs @@ -946,6 +946,17 @@ impl<'de, R: Read<'de>> Deserializer { } } } + + #[cfg(feature = "raw_value")] + fn deserialize_raw_value(&mut self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.parse_whitespace()?; + self.read.begin_raw_buffering(); + self.ignore_value()?; + self.read.end_raw_buffering(visitor) + } } impl FromStr for Number { @@ -1412,10 +1423,18 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer { /// Parses a newtype struct as the underlying value. #[inline] - fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result + fn deserialize_newtype_struct(self, name: &str, visitor: V) -> Result where V: de::Visitor<'de>, { + #[cfg(feature = "raw_value")] + { + if name == ::raw::TOKEN { + return self.deserialize_raw_value(visitor); + } + } + + let _ = name; visitor.visit_newtype_struct(self) } diff --git a/src/lib.rs b/src/lib.rs index d9b79175e..79513b320 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -389,3 +389,6 @@ pub mod value; mod iter; mod number; mod read; + +#[cfg(feature = "raw_value")] +mod raw; diff --git a/src/number.rs b/src/number.rs index cc6bccb6c..fcf98ee78 100644 --- a/src/number.rs +++ b/src/number.rs @@ -26,12 +26,7 @@ use error::ErrorCode; #[cfg(feature = "arbitrary_precision")] /// Not public API. Should be pub(crate). #[doc(hidden)] -pub const SERDE_STRUCT_FIELD_NAME: &'static str = "$__serde_private_number"; - -#[cfg(feature = "arbitrary_precision")] -/// Not public API. Should be pub(crate). -#[doc(hidden)] -pub const SERDE_STRUCT_NAME: &'static str = "$__serde_private_Number"; +pub const TOKEN: &'static str = "$serde_json::private::Number"; /// Represents a JSON number, whether integer or floating point. #[derive(Clone, PartialEq)] @@ -346,8 +341,8 @@ impl Serialize for Number { { use serde::ser::SerializeStruct; - let mut s = serializer.serialize_struct(SERDE_STRUCT_NAME, 1)?; - s.serialize_field(SERDE_STRUCT_FIELD_NAME, &self.n)?; + let mut s = serializer.serialize_struct(TOKEN, 1)?; + s.serialize_field(TOKEN, &self.n)?; s.end() } } @@ -426,7 +421,7 @@ impl<'de> de::Deserialize<'de> for NumberKey { where E: de::Error, { - if s == SERDE_STRUCT_FIELD_NAME { + if s == TOKEN { Ok(()) } else { Err(de::Error::custom("expected field with custom name")) @@ -638,7 +633,7 @@ impl<'de> Deserializer<'de> for NumberFieldDeserializer { where V: de::Visitor<'de>, { - visitor.visit_borrowed_str(SERDE_STRUCT_FIELD_NAME) + visitor.visit_borrowed_str(TOKEN) } forward_to_deserialize_any! { diff --git a/src/raw.rs b/src/raw.rs new file mode 100644 index 000000000..54b85c79c --- /dev/null +++ b/src/raw.rs @@ -0,0 +1,445 @@ +use std::fmt::{self, Debug, Display}; +use std::mem; + +use serde::ser::{Serialize, Serializer, SerializeStruct}; +use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor}; +use serde::de::value::BorrowedStrDeserializer; + +use error::Error; + +/// Reference to a range of bytes encompassing a single valid JSON value in the +/// input data. +/// +/// A `RawValue` can be used to defer parsing parts of a payload until later, +/// or to avoid parsing it at all in the case that part of the payload just +/// needs to be transferred verbatim into a different output object. +/// +/// When serializing, a value of this type will retain its original formatting +/// and will not be minified or pretty-printed. +/// +/// # Example +/// +/// ``` +/// #[macro_use] +/// extern crate serde_derive; +/// extern crate serde_json; +/// +/// use serde_json::{Result, value::RawValue}; +/// +/// #[derive(Deserialize)] +/// struct Input<'a> { +/// code: u32, +/// #[serde(borrow)] +/// payload: &'a RawValue, +/// } +/// +/// #[derive(Serialize)] +/// struct Output<'a> { +/// info: (u32, &'a RawValue), +/// } +/// +/// // Efficiently rearrange JSON input containing separate "code" and "payload" +/// // keys into a single "info" key holding an array of code and payload. +/// // +/// // This could be done equivalently using serde_json::Value as the type for +/// // payload, but &RawValue will perform netter because it does not require +/// // memory allocation. The correct range of bytes is borrowed from the input +/// // data and pasted verbatim into the output. +/// fn rearrange(input: &str) -> Result { +/// let input: Input = serde_json::from_str(input)?; +/// +/// let output = Output { +/// info: (input.code, input.payload), +/// }; +/// +/// serde_json::to_string(&output) +/// } +/// +/// fn main() -> Result<()> { +/// let out = rearrange(r#" {"code": 200, "payload": {}} "#)?; +/// +/// assert_eq!(out, r#"{"info":[200,{}]}"#); +/// +/// Ok(()) +/// } +/// ``` +/// +/// # Ownership +/// +/// The typical usage of `RawValue` will be in the borrowed form: +/// +/// ``` +/// # #[macro_use] +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # +/// # use serde_json::value::RawValue; +/// # +/// #[derive(Deserialize)] +/// struct SomeStruct<'a> { +/// #[serde(borrow)] +/// raw_value: &'a RawValue, +/// } +/// # +/// # fn main() {} +/// ``` +/// +/// The borrowed form is suitable when deserializing through +/// [`serde_json::from_str`] and [`serde_json::from_slice`] which support +/// borrowing from the input data without memory allocation. +/// +/// When deserializing through [`serde_json::from_reader`] you will need to use +/// the boxed form of `RawValue` instead. This is almost as efficient but +/// involves buffering the raw value from the I/O stream into memory. +/// +/// [`serde_json::from_str`]: ../fn.from_str.html +/// [`serde_json::from_slice`]: ../fn.from_slice.html +/// [`serde_json::from_reader`]: ../fn.from_reader.html +/// +/// ``` +/// # #[macro_use] +/// # extern crate serde_derive; +/// # extern crate serde_json; +/// # +/// # use serde_json::value::RawValue; +/// # +/// #[derive(Deserialize)] +/// struct SomeStruct { +/// raw_value: Box, +/// } +/// # +/// # fn main() {} +/// ``` +/// +/// # Note +/// +/// `RawValue` is only available if serde\_json is built with the `"raw_value"` +/// feature. +/// +/// ```toml +/// [dependencies] +/// serde_json = { version = "1.0", features = ["raw_value"] } +/// ``` +#[repr(C)] +pub struct RawValue { + json: str, +} + +impl RawValue { + fn from_borrowed(json: &str) -> &Self { + unsafe { mem::transmute::<&str, &RawValue>(json) } + } + + fn from_owned(json: Box) -> Box { + unsafe { mem::transmute::, Box>(json) } + } +} + +impl Clone for Box { + fn clone(&self) -> Self { + (**self).to_owned() + } +} + +impl ToOwned for RawValue { + type Owned = Box; + + fn to_owned(&self) -> Self::Owned { + RawValue::from_owned(self.json.to_owned().into_boxed_str()) + } +} + +impl Debug for RawValue { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter + .debug_tuple("RawValue") + .field(&format_args!("{}", &self.json)) + .finish() + } +} + +impl Display for RawValue { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.json) + } +} + +impl RawValue { + /// Access the JSON text underlying a raw value. + /// + /// # Example + /// + /// ``` + /// #[macro_use] + /// extern crate serde_derive; + /// extern crate serde_json; + /// + /// use serde_json::{Result, value::RawValue}; + /// + /// #[derive(Deserialize)] + /// struct Response<'a> { + /// code: u32, + /// #[serde(borrow)] + /// payload: &'a RawValue, + /// } + /// + /// fn process(input: &str) -> Result<()> { + /// let response: Response = serde_json::from_str(input)?; + /// + /// let payload = response.payload.get(); + /// if payload.starts_with('{') { + /// // handle a payload which is a JSON map + /// } else { + /// // handle any other type + /// } + /// + /// Ok(()) + /// } + /// + /// fn main() -> Result<()> { + /// process(r#" {"code": 200, "payload": {}} "#)?; + /// Ok(()) + /// } + /// ``` + pub fn get(&self) -> &str { + &self.json + } +} + +pub const TOKEN: &'static str = "$serde_json::private::RawValue"; + +impl Serialize for RawValue { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut s = serializer.serialize_struct(TOKEN, 1)?; + s.serialize_field(TOKEN, &self.json)?; + s.end() + } +} + +impl<'de: 'a, 'a> Deserialize<'de> for &'a RawValue { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ReferenceVisitor; + + impl<'de> Visitor<'de> for ReferenceVisitor { + type Value = &'de RawValue; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "any valid JSON value") + } + + fn visit_map(self, mut visitor: V) -> Result + where + V: MapAccess<'de>, + { + let value = visitor.next_key::()?; + if value.is_none() { + return Err(de::Error::invalid_type(Unexpected::Map, &self)); + } + visitor.next_value_seed(ReferenceFromString) + } + } + + deserializer.deserialize_newtype_struct(TOKEN, ReferenceVisitor) + } +} + +impl<'de> Deserialize<'de> for Box { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct BoxedVisitor; + + impl<'de> Visitor<'de> for BoxedVisitor { + type Value = Box; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "any valid JSON value") + } + + fn visit_map(self, mut visitor: V) -> Result + where + V: MapAccess<'de>, + { + let value = visitor.next_key::()?; + if value.is_none() { + return Err(de::Error::invalid_type(Unexpected::Map, &self)); + } + visitor.next_value_seed(BoxedFromString) + } + } + + deserializer.deserialize_newtype_struct(TOKEN, BoxedVisitor) + } +} + +struct RawKey; + +impl<'de> Deserialize<'de> for RawKey { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct FieldVisitor; + + impl<'de> Visitor<'de> for FieldVisitor { + type Value = (); + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("raw value") + } + + fn visit_str(self, s: &str) -> Result<(), E> + where + E: de::Error, + { + if s == TOKEN { + Ok(()) + } else { + Err(de::Error::custom("unexpected raw value")) + } + } + } + + deserializer.deserialize_identifier(FieldVisitor)?; + Ok(RawKey) + } +} + +pub struct ReferenceFromString; + +impl<'de> DeserializeSeed<'de> for ReferenceFromString { + type Value = &'de RawValue; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(self) + } +} + +impl<'de> Visitor<'de> for ReferenceFromString { + type Value = &'de RawValue; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("raw value") + } + + fn visit_borrowed_str(self, s: &'de str) -> Result + where + E: de::Error, + { + Ok(RawValue::from_borrowed(s)) + } +} + +pub struct BoxedFromString; + +impl<'de> DeserializeSeed<'de> for BoxedFromString { + type Value = Box; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(self) + } +} + +impl<'de> Visitor<'de> for BoxedFromString { + type Value = Box; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("raw value") + } + + fn visit_str(self, s: &str) -> Result + where + E: de::Error, + { + self.visit_string(s.to_owned()) + } + + fn visit_string(self, s: String) -> Result + where + E: de::Error, + { + Ok(RawValue::from_owned(s.into_boxed_str())) + } +} + +struct RawKeyDeserializer; + +impl<'de> Deserializer<'de> for RawKeyDeserializer { + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_borrowed_str(TOKEN) + } + + forward_to_deserialize_any! { + bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 char str string seq + bytes byte_buf map struct option unit newtype_struct ignored_any + unit_struct tuple_struct tuple enum identifier + } +} + +pub struct OwnedRawDeserializer { + pub raw_value: Option, +} + +impl<'de> MapAccess<'de> for OwnedRawDeserializer { + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result, Error> + where + K: de::DeserializeSeed<'de>, + { + if self.raw_value.is_none() { + return Ok(None); + } + seed.deserialize(RawKeyDeserializer).map(Some) + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>, + { + seed.deserialize(self.raw_value.take().unwrap().into_deserializer()) + } +} + +pub struct BorrowedRawDeserializer<'de> { + pub raw_value: Option<&'de str>, +} + +impl<'de> MapAccess<'de> for BorrowedRawDeserializer<'de> { + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result, Error> + where + K: de::DeserializeSeed<'de>, + { + if self.raw_value.is_none() { + return Ok(None); + } + seed.deserialize(RawKeyDeserializer).map(Some) + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>, + { + seed.deserialize(BorrowedStrDeserializer::new(self.raw_value.take().unwrap())) + } +} diff --git a/src/read.rs b/src/read.rs index f2cc9f93b..fba1dd9f9 100644 --- a/src/read.rs +++ b/src/read.rs @@ -9,9 +9,15 @@ use std::ops::Deref; use std::{char, cmp, io, str}; +#[cfg(feature = "raw_value")] +use serde::de::Visitor; + use iter::LineColIterator; -use super::error::{Error, ErrorCode, Result}; +use error::{Error, ErrorCode, Result}; + +#[cfg(feature = "raw_value")] +use raw::{BorrowedRawDeserializer, OwnedRawDeserializer}; /// Trait used by the deserializer for iterating over input. This is manually /// "specialized" for iterating over &[u8]. Once feature(specialization) is @@ -76,6 +82,21 @@ pub trait Read<'de>: private::Sealed { /// string until the next quotation mark but discards the data. #[doc(hidden)] fn ignore_str(&mut self) -> Result<()>; + + /// Switch raw buffering mode on. + /// + /// This is used when deserializing `RawValue`. + #[cfg(feature = "raw_value")] + #[doc(hidden)] + fn begin_raw_buffering(&mut self); + + /// Switch raw buffering mode off and provides the raw buffered data to the + /// given visitor. + #[cfg(feature = "raw_value")] + #[doc(hidden)] + fn end_raw_buffering(&mut self, visitor: V) -> Result + where + V: Visitor<'de>; } pub struct Position { @@ -107,6 +128,8 @@ where iter: LineColIterator>, /// Temporary storage of peeked byte. ch: Option, + #[cfg(feature = "raw_value")] + raw_buffer: Option>, } /// JSON input source that reads from a slice of bytes. @@ -117,6 +140,8 @@ pub struct SliceRead<'a> { slice: &'a [u8], /// Index of the *next* byte that will be returned by next() or peek(). index: usize, + #[cfg(feature = "raw_value")] + raw_buffering_start_index: usize, } /// JSON input source that reads from a UTF-8 string. @@ -124,6 +149,8 @@ pub struct SliceRead<'a> { // Able to elide UTF-8 checks by assuming that the input is valid UTF-8. pub struct StrRead<'a> { delegate: SliceRead<'a>, + #[cfg(feature = "raw_value")] + data: &'a str, } // Prevent users from implementing the Read trait. @@ -139,9 +166,20 @@ where { /// Create a JSON input source to read from a std::io input stream. pub fn new(reader: R) -> Self { - IoRead { - iter: LineColIterator::new(reader.bytes()), - ch: None, + #[cfg(not(feature = "raw_value"))] + { + IoRead { + iter: LineColIterator::new(reader.bytes()), + ch: None, + } + } + #[cfg(feature = "raw_value")] + { + IoRead { + iter: LineColIterator::new(reader.bytes()), + ch: None, + raw_buffer: None, + } } } } @@ -193,10 +231,26 @@ where #[inline] fn next(&mut self) -> io::Result> { match self.ch.take() { - Some(ch) => Ok(Some(ch)), + Some(ch) => { + #[cfg(feature = "raw_value")] + { + if let Some(ref mut buf) = self.raw_buffer { + buf.push(ch); + } + } + Ok(Some(ch)) + } None => match self.iter.next() { Some(Err(err)) => Err(err), - Some(Ok(ch)) => Ok(Some(ch)), + Some(Ok(ch)) => { + #[cfg(feature = "raw_value")] + { + if let Some(ref mut buf) = self.raw_buffer { + buf.push(ch); + } + } + Ok(Some(ch)) + } None => Ok(None), }, } @@ -217,11 +271,21 @@ where } } + #[cfg(not(feature = "raw_value"))] #[inline] fn discard(&mut self) { self.ch = None; } + #[cfg(feature = "raw_value")] + fn discard(&mut self) { + if let Some(ch) = self.ch.take() { + if let Some(ref mut buf) = self.raw_buffer { + buf.push(ch); + } + } + } + fn position(&self) -> Position { Position { line: self.iter.line(), @@ -274,6 +338,21 @@ where } } } + + #[cfg(feature = "raw_value")] + fn begin_raw_buffering(&mut self) { + self.raw_buffer = Some(Vec::new()); + } + + #[cfg(feature = "raw_value")] + fn end_raw_buffering(&mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let raw = self.raw_buffer.take().unwrap(); + let raw = String::from_utf8(raw).unwrap(); + visitor.visit_map(OwnedRawDeserializer { raw_value: Some(raw) }) + } } ////////////////////////////////////////////////////////////////////////////// @@ -281,9 +360,20 @@ where impl<'a> SliceRead<'a> { /// Create a JSON input source to read from a slice of bytes. pub fn new(slice: &'a [u8]) -> Self { - SliceRead { - slice: slice, - index: 0, + #[cfg(not(feature = "raw_value"))] + { + SliceRead { + slice: slice, + index: 0, + } + } + #[cfg(feature = "raw_value")] + { + SliceRead { + slice: slice, + index: 0, + raw_buffering_start_index: 0, + } } } @@ -437,6 +527,21 @@ impl<'a> Read<'a> for SliceRead<'a> { } } } + + #[cfg(feature = "raw_value")] + fn begin_raw_buffering(&mut self) { + self.raw_buffering_start_index = self.index; + } + + #[cfg(feature = "raw_value")] + fn end_raw_buffering(&mut self, visitor: V) -> Result + where + V: Visitor<'a>, + { + let raw = &self.slice[self.raw_buffering_start_index..self.index]; + let raw = str::from_utf8(raw).unwrap(); + visitor.visit_map(BorrowedRawDeserializer { raw_value: Some(raw) }) + } } ////////////////////////////////////////////////////////////////////////////// @@ -444,8 +549,18 @@ impl<'a> Read<'a> for SliceRead<'a> { impl<'a> StrRead<'a> { /// Create a JSON input source to read from a UTF-8 string. pub fn new(s: &'a str) -> Self { - StrRead { - delegate: SliceRead::new(s.as_bytes()), + #[cfg(not(feature = "raw_value"))] + { + StrRead { + delegate: SliceRead::new(s.as_bytes()), + } + } + #[cfg(feature = "raw_value")] + { + StrRead { + delegate: SliceRead::new(s.as_bytes()), + data: s, + } } } } @@ -498,6 +613,20 @@ impl<'a> Read<'a> for StrRead<'a> { fn ignore_str(&mut self) -> Result<()> { self.delegate.ignore_str() } + + #[cfg(feature = "raw_value")] + fn begin_raw_buffering(&mut self) { + self.delegate.begin_raw_buffering() + } + + #[cfg(feature = "raw_value")] + fn end_raw_buffering(&mut self, visitor: V) -> Result + where + V: Visitor<'a>, + { + let raw = &self.data[self.delegate.raw_buffering_start_index..self.delegate.index]; + visitor.visit_map(BorrowedRawDeserializer { raw_value: Some(raw) }) + } } ////////////////////////////////////////////////////////////////////////////// diff --git a/src/ser.rs b/src/ser.rs index ca9b637ee..eceb4e6b4 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -14,14 +14,11 @@ use std::num::FpCategory; use std::str; use super::error::{Error, ErrorCode, Result}; -use serde::ser::{self, Impossible}; +use serde::ser::{self, Impossible, Serialize}; use itoa; use ryu; -#[cfg(feature = "arbitrary_precision")] -use serde::Serialize; - /// A structure for serializing Rust values into JSON. pub struct Serializer { writer: W, @@ -288,7 +285,7 @@ where #[inline] fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { value.serialize(self) } @@ -302,7 +299,7 @@ where value: &T, ) -> Result<()> where - T: ser::Serialize, + T: Serialize, { try!( self.formatter @@ -347,7 +344,7 @@ where #[inline] fn serialize_some(self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { value.serialize(self) } @@ -462,7 +459,9 @@ where fn serialize_struct(self, name: &'static str, len: usize) -> Result { match name { #[cfg(feature = "arbitrary_precision")] - ::number::SERDE_STRUCT_NAME => Ok(Compound::Number { ser: self }), + ::number::TOKEN => Ok(Compound::Number { ser: self }), + #[cfg(feature = "raw_value")] + ::raw::TOKEN => Ok(Compound::RawValue { ser: self }), _ => self.serialize_map(Some(len)), } } @@ -573,6 +572,8 @@ pub enum Compound<'a, W: 'a, F: 'a> { }, #[cfg(feature = "arbitrary_precision")] Number { ser: &'a mut Serializer }, + #[cfg(feature = "raw_value")] + RawValue { ser: &'a mut Serializer }, } impl<'a, W, F> ser::SerializeSeq for Compound<'a, W, F> @@ -586,7 +587,7 @@ where #[inline] fn serialize_element(&mut self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { match *self { Compound::Map { @@ -609,6 +610,8 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + Compound::RawValue { .. } => unreachable!(), } } @@ -624,6 +627,8 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + Compound::RawValue { .. } => unreachable!(), } } } @@ -639,7 +644,7 @@ where #[inline] fn serialize_element(&mut self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { ser::SerializeSeq::serialize_element(self, value) } @@ -661,7 +666,7 @@ where #[inline] fn serialize_field(&mut self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { ser::SerializeSeq::serialize_element(self, value) } @@ -683,7 +688,7 @@ where #[inline] fn serialize_field(&mut self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { ser::SerializeSeq::serialize_element(self, value) } @@ -706,6 +711,8 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + Compound::RawValue { .. } => unreachable!(), } } } @@ -721,7 +728,7 @@ where #[inline] fn serialize_key(&mut self, key: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { match *self { Compound::Map { @@ -746,13 +753,15 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + Compound::RawValue { .. } => unreachable!(), } } #[inline] fn serialize_value(&mut self, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { match *self { Compound::Map { ref mut ser, .. } => { @@ -771,6 +780,8 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + Compound::RawValue { .. } => unreachable!(), } } @@ -786,6 +797,8 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + Compound::RawValue { .. } => unreachable!(), } } } @@ -801,7 +814,7 @@ where #[inline] fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { match *self { Compound::Map { .. } => { @@ -810,13 +823,22 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { ref mut ser, .. } => { - if key == ::number::SERDE_STRUCT_FIELD_NAME { + if key == ::number::TOKEN { try!(value.serialize(NumberStrEmitter(&mut *ser))); Ok(()) } else { Err(invalid_number()) } } + #[cfg(feature = "raw_value")] + Compound::RawValue { ref mut ser, .. } => { + if key == ::raw::TOKEN { + try!(value.serialize(RawValueStrEmitter(&mut *ser))); + Ok(()) + } else { + Err(invalid_raw_value()) + } + } } } @@ -826,6 +848,8 @@ where Compound::Map { .. } => ser::SerializeMap::end(self), #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => Ok(()), + #[cfg(feature = "raw_value")] + Compound::RawValue { .. } => Ok(()), } } } @@ -841,12 +865,14 @@ where #[inline] fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { match *self { Compound::Map { .. } => ser::SerializeStruct::serialize_field(self, key, value), #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + Compound::RawValue { .. } => unreachable!(), } } @@ -868,6 +894,8 @@ where } #[cfg(feature = "arbitrary_precision")] Compound::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + Compound::RawValue { .. } => unreachable!(), } } } @@ -881,6 +909,11 @@ fn invalid_number() -> Error { Error::syntax(ErrorCode::InvalidNumber, 0, 0) } +#[cfg(feature = "raw_value")] +fn invalid_raw_value() -> Error { + Error::syntax(ErrorCode::ExpectedSomeValue, 0, 0) +} + fn key_must_be_a_string() -> Error { Error::syntax(ErrorCode::KeyMustBeAString, 0, 0) } @@ -911,7 +944,7 @@ where #[inline] fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { value.serialize(self) } @@ -1154,7 +1187,7 @@ where _value: &T, ) -> Result<()> where - T: ser::Serialize, + T: Serialize, { Err(key_must_be_a_string()) } @@ -1165,7 +1198,7 @@ where fn serialize_some(self, _value: &T) -> Result<()> where - T: ser::Serialize, + T: Serialize, { Err(key_must_be_a_string()) } @@ -1400,6 +1433,191 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W, } } +#[cfg(feature = "raw_value")] +struct RawValueStrEmitter<'a, W: 'a + io::Write, F: 'a + Formatter>(&'a mut Serializer); + +#[cfg(feature = "raw_value")] +impl<'a, W: io::Write, F: Formatter> ser::Serializer for RawValueStrEmitter<'a, W, F> { + type Ok = (); + type Error = Error; + + type SerializeSeq = Impossible<(), Error>; + type SerializeTuple = Impossible<(), Error>; + type SerializeTupleStruct = Impossible<(), Error>; + type SerializeTupleVariant = Impossible<(), Error>; + type SerializeMap = Impossible<(), Error>; + type SerializeStruct = Impossible<(), Error>; + type SerializeStructVariant = Impossible<(), Error>; + + fn serialize_bool(self, _v: bool) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i8(self, _v: i8) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i16(self, _v: i16) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i32(self, _v: i32) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_i64(self, _v: i64) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + serde_if_integer128! { + fn serialize_i128(self, _v: i128) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + } + + fn serialize_u8(self, _v: u8) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_u16(self, _v: u16) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_u32(self, _v: u32) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_u64(self, _v: u64) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + serde_if_integer128! { + fn serialize_u128(self, _v: u128) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + } + + fn serialize_f32(self, _v: f32) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_f64(self, _v: f64) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_char(self, _v: char) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_str(self, value: &str) -> Result { + let RawValueStrEmitter(serializer) = self; + serializer + .formatter + .write_raw_fragment(&mut serializer.writer, value) + .map_err(Error::io) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_none(self) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_some(self, _value: &T) -> Result + where + T: Serialize, + { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_unit(self) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + _value: &T, + ) -> Result + where + T: Serialize, + { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result + where + T: Serialize, + { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_seq(self, _len: Option) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_map(self, _len: Option) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { + Err(ser::Error::custom("expected RawValue")) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(ser::Error::custom("expected RawValue")) + } +} + /// Represents a character escape code in a type-safe manner. pub enum CharEscape { /// An escaped quote `"` @@ -1743,6 +1961,16 @@ pub trait Formatter { { Ok(()) } + + /// Writes a raw JSON fragment that doesn't need any escaping to the + /// specified writer. + #[inline] + fn write_raw_fragment(&mut self, writer: &mut W, fragment: &str) -> io::Result<()> + where + W: io::Write, + { + writer.write_all(fragment.as_bytes()) + } } /// This structure compacts a JSON value with no extra whitespace. @@ -1979,7 +2207,7 @@ static ESCAPE: [u8; 256] = [ pub fn to_writer(writer: W, value: &T) -> Result<()> where W: io::Write, - T: ser::Serialize, + T: Serialize, { let mut ser = Serializer::new(writer); try!(value.serialize(&mut ser)); @@ -1997,7 +2225,7 @@ where pub fn to_writer_pretty(writer: W, value: &T) -> Result<()> where W: io::Write, - T: ser::Serialize, + T: Serialize, { let mut ser = Serializer::pretty(writer); try!(value.serialize(&mut ser)); @@ -2013,7 +2241,7 @@ where #[inline] pub fn to_vec(value: &T) -> Result> where - T: ser::Serialize, + T: Serialize, { let mut writer = Vec::with_capacity(128); try!(to_writer(&mut writer, value)); @@ -2029,7 +2257,7 @@ where #[inline] pub fn to_vec_pretty(value: &T) -> Result> where - T: ser::Serialize, + T: Serialize, { let mut writer = Vec::with_capacity(128); try!(to_writer_pretty(&mut writer, value)); @@ -2045,7 +2273,7 @@ where #[inline] pub fn to_string(value: &T) -> Result where - T: ser::Serialize, + T: Serialize, { let vec = try!(to_vec(value)); let string = unsafe { @@ -2064,7 +2292,7 @@ where #[inline] pub fn to_string_pretty(value: &T) -> Result where - T: ser::Serialize, + T: Serialize, { let vec = try!(to_vec_pretty(value)); let string = unsafe { diff --git a/src/value/de.rs b/src/value/de.rs index dc8dbc6be..ba99840c5 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -116,7 +116,12 @@ impl<'de> Deserialize<'de> for Value { #[cfg(feature = "arbitrary_precision")] Some(KeyClass::Number) => { let number: NumberFromString = visitor.next_value()?; - return Ok(Value::Number(number.value)); + Ok(Value::Number(number.value)) + } + #[cfg(feature = "raw_value")] + Some(KeyClass::RawValue) => { + let value = visitor.next_value_seed(::raw::BoxedFromString)?; + ::from_str(value.get()).map_err(de::Error::custom) } Some(KeyClass::Map(first_key)) => { let mut values = Map::new(); @@ -300,12 +305,22 @@ impl<'de> serde::Deserializer<'de> for Value { #[inline] fn deserialize_newtype_struct( self, - _name: &'static str, + name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { + #[cfg(feature = "raw_value")] + { + if name == ::raw::TOKEN { + return visitor.visit_map(::raw::OwnedRawDeserializer { + raw_value: Some(self.to_string()), + }); + } + } + + let _ = name; visitor.visit_newtype_struct(self) } @@ -829,12 +844,22 @@ impl<'de> serde::Deserializer<'de> for &'de Value { #[inline] fn deserialize_newtype_struct( self, - _name: &'static str, + name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { + #[cfg(feature = "raw_value")] + { + if name == ::raw::TOKEN { + return visitor.visit_map(::raw::OwnedRawDeserializer { + raw_value: Some(self.to_string()), + }); + } + } + + let _ = name; visitor.visit_newtype_struct(self) } @@ -1292,6 +1317,8 @@ enum KeyClass { Map(String), #[cfg(feature = "arbitrary_precision")] Number, + #[cfg(feature = "raw_value")] + RawValue, } impl<'de> DeserializeSeed<'de> for KeyClassifier { @@ -1318,7 +1345,9 @@ impl<'de> Visitor<'de> for KeyClassifier { { match s { #[cfg(feature = "arbitrary_precision")] - ::number::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::Number), + ::number::TOKEN => Ok(KeyClass::Number), + #[cfg(feature = "raw_value")] + ::raw::TOKEN => Ok(KeyClass::RawValue), _ => Ok(KeyClass::Map(s.to_owned())), } } @@ -1329,7 +1358,9 @@ impl<'de> Visitor<'de> for KeyClassifier { { match s.as_str() { #[cfg(feature = "arbitrary_precision")] - ::number::SERDE_STRUCT_FIELD_NAME => Ok(KeyClass::Number), + ::number::TOKEN => Ok(KeyClass::Number), + #[cfg(feature = "raw_value")] + ::raw::TOKEN => Ok(KeyClass::RawValue), _ => Ok(KeyClass::Map(s)), } } diff --git a/src/value/mod.rs b/src/value/mod.rs index f5e33b457..c976af501 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -119,6 +119,9 @@ use error::Error; pub use map::Map; pub use number::Number; +#[cfg(feature = "raw_value")] +pub use raw::RawValue; + pub use self::index::Index; use self::ser::Serializer; diff --git a/src/value/ser.rs b/src/value/ser.rs index d3f71b373..172784cce 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -14,9 +14,6 @@ use map::Map; use number::Number; use value::{to_value, Value}; -#[cfg(feature = "arbitrary_precision")] -use serde::ser; - impl Serialize for Value { #[inline] fn serialize(&self, serializer: S) -> Result @@ -232,7 +229,9 @@ impl serde::Serializer for Serializer { ) -> Result { match name { #[cfg(feature = "arbitrary_precision")] - ::number::SERDE_STRUCT_NAME => Ok(SerializeMap::Number { out_value: None }), + ::number::TOKEN => Ok(SerializeMap::Number { out_value: None }), + #[cfg(feature = "raw_value")] + ::raw::TOKEN => Ok(SerializeMap::RawValue { out_value: None }), _ => self.serialize_map(Some(len)), } } @@ -267,6 +266,8 @@ pub enum SerializeMap { }, #[cfg(feature = "arbitrary_precision")] Number { out_value: Option }, + #[cfg(feature = "raw_value")] + RawValue { out_value: Option }, } pub struct SerializeStructVariant { @@ -361,6 +362,8 @@ impl serde::ser::SerializeMap for SerializeMap { } #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + SerializeMap::RawValue { .. } => unreachable!(), } } @@ -382,6 +385,8 @@ impl serde::ser::SerializeMap for SerializeMap { } #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + SerializeMap::RawValue { .. } => unreachable!(), } } @@ -390,6 +395,8 @@ impl serde::ser::SerializeMap for SerializeMap { SerializeMap::Map { map, .. } => Ok(Value::Object(map)), #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { .. } => unreachable!(), + #[cfg(feature = "raw_value")] + SerializeMap::RawValue { .. } => unreachable!(), } } } @@ -592,13 +599,22 @@ impl serde::ser::SerializeStruct for SerializeMap { } #[cfg(feature = "arbitrary_precision")] SerializeMap::Number { ref mut out_value } => { - if key == ::number::SERDE_STRUCT_FIELD_NAME { + if key == ::number::TOKEN { *out_value = Some(value.serialize(NumberValueEmitter)?); Ok(()) } else { Err(invalid_number()) } } + #[cfg(feature = "raw_value")] + SerializeMap::RawValue { ref mut out_value } => { + if key == ::raw::TOKEN { + *out_value = Some(value.serialize(RawValueEmitter)?); + Ok(()) + } else { + Err(invalid_raw_value()) + } + } } } @@ -609,6 +625,10 @@ impl serde::ser::SerializeStruct for SerializeMap { SerializeMap::Number { out_value, .. } => { Ok(out_value.expect("number value was not emitted")) } + #[cfg(feature = "raw_value")] + SerializeMap::RawValue { out_value, .. } => { + Ok(out_value.expect("raw value was not emitted")) + } } } } @@ -643,7 +663,7 @@ fn invalid_number() -> Error { } #[cfg(feature = "arbitrary_precision")] -impl ser::Serializer for NumberValueEmitter { +impl serde::ser::Serializer for NumberValueEmitter { type Ok = Value; type Error = Error; @@ -812,3 +832,181 @@ impl ser::Serializer for NumberValueEmitter { Err(invalid_number()) } } + +#[cfg(feature = "raw_value")] +struct RawValueEmitter; + +#[cfg(feature = "raw_value")] +fn invalid_raw_value() -> Error { + Error::syntax(ErrorCode::ExpectedSomeValue, 0, 0) +} + +#[cfg(feature = "raw_value")] +impl serde::ser::Serializer for RawValueEmitter { + type Ok = Value; + type Error = Error; + + type SerializeSeq = Impossible; + type SerializeTuple = Impossible; + type SerializeTupleStruct = Impossible; + type SerializeTupleVariant = Impossible; + type SerializeMap = Impossible; + type SerializeStruct = Impossible; + type SerializeStructVariant = Impossible; + + fn serialize_bool(self, _v: bool) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_i8(self, _v: i8) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_i16(self, _v: i16) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_i32(self, _v: i32) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_i64(self, _v: i64) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_u8(self, _v: u8) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_u16(self, _v: u16) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_u32(self, _v: u32) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_u64(self, _v: u64) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_f32(self, _v: f32) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_f64(self, _v: f64) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_char(self, _v: char) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_str(self, value: &str) -> Result { + ::from_str(value) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_none(self) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_some(self, _value: &T) -> Result + where + T: Serialize, + { + Err(invalid_raw_value()) + } + + fn serialize_unit(self) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + _value: &T, + ) -> Result + where + T: Serialize, + { + Err(invalid_raw_value()) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result + where + T: Serialize, + { + Err(invalid_raw_value()) + } + + fn serialize_seq(self, _len: Option) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_map(self, _len: Option) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(invalid_raw_value()) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(invalid_raw_value()) + } +} diff --git a/tests/test.rs b/tests/test.rs index 08d038837..ec2de425e 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -938,9 +938,9 @@ fn test_serialize_char() { #[test] fn test_malicious_number() { #[derive(Serialize)] - #[serde(rename = "$__serde_private_Number")] + #[serde(rename = "$serde_json::private::Number")] struct S { - #[serde(rename = "$__serde_private_number")] + #[serde(rename = "$serde_json::private::Number")] f: &'static str, } @@ -2039,3 +2039,88 @@ fn test_integer128() { ), ]); } + +#[cfg(feature = "raw_value")] +#[test] +fn test_borrowed_raw_value() { + use serde_json::value::RawValue; + + #[derive(Serialize, Deserialize)] + struct Wrapper<'a> { + a: i8, + #[serde(borrow)] + b: &'a RawValue, + c: i8, + }; + + let wrapper_from_str: Wrapper = + serde_json::from_str(r#"{"a": 1, "b": {"foo": 2}, "c": 3}"#).unwrap(); + assert_eq!(r#"{"foo": 2}"#, wrapper_from_str.b.get()); + + let wrapper_to_string = serde_json::to_string(&wrapper_from_str).unwrap(); + assert_eq!(r#"{"a":1,"b":{"foo": 2},"c":3}"#, wrapper_to_string); + + let wrapper_to_value = serde_json::to_value(&wrapper_from_str).unwrap(); + assert_eq!(json!({"a": 1, "b": {"foo": 2}, "c": 3}), wrapper_to_value); + + let array_from_str: Vec<&RawValue> = + serde_json::from_str(r#"["a", 42, {"foo": "bar"}, null]"#).unwrap(); + assert_eq!(r#""a""#, array_from_str[0].get()); + assert_eq!(r#"42"#, array_from_str[1].get()); + assert_eq!(r#"{"foo": "bar"}"#, array_from_str[2].get()); + assert_eq!(r#"null"#, array_from_str[3].get()); + + let array_to_string = serde_json::to_string(&array_from_str).unwrap(); + assert_eq!(r#"["a",42,{"foo": "bar"},null]"#, array_to_string); +} + +#[cfg(feature = "raw_value")] +#[test] +fn test_boxed_raw_value() { + use serde_json::value::RawValue; + + #[derive(Serialize, Deserialize)] + struct Wrapper { + a: i8, + b: Box, + c: i8, + }; + + let wrapper_from_str: Wrapper = + serde_json::from_str(r#"{"a": 1, "b": {"foo": 2}, "c": 3}"#).unwrap(); + assert_eq!(r#"{"foo": 2}"#, wrapper_from_str.b.get()); + + let wrapper_from_reader: Wrapper = serde_json::from_reader( + br#"{"a": 1, "b": {"foo": 2}, "c": 3}"#.as_ref(), + ).unwrap(); + assert_eq!(r#"{"foo": 2}"#, wrapper_from_reader.b.get()); + + let wrapper_from_value: Wrapper = + serde_json::from_value(json!({"a": 1, "b": {"foo": 2}, "c": 3})) + .unwrap(); + assert_eq!(r#"{"foo":2}"#, wrapper_from_value.b.get()); + + let wrapper_to_string = serde_json::to_string(&wrapper_from_str).unwrap(); + assert_eq!(r#"{"a":1,"b":{"foo": 2},"c":3}"#, wrapper_to_string); + + let wrapper_to_value = serde_json::to_value(&wrapper_from_str).unwrap(); + assert_eq!(json!({"a": 1, "b": {"foo": 2}, "c": 3}), wrapper_to_value); + + let array_from_str: Vec> = + serde_json::from_str(r#"["a", 42, {"foo": "bar"}, null]"#).unwrap(); + assert_eq!(r#""a""#, array_from_str[0].get()); + assert_eq!(r#"42"#, array_from_str[1].get()); + assert_eq!(r#"{"foo": "bar"}"#, array_from_str[2].get()); + assert_eq!(r#"null"#, array_from_str[3].get()); + + let array_from_reader: Vec> = serde_json::from_reader( + br#"["a", 42, {"foo": "bar"}, null]"#.as_ref(), + ).unwrap(); + assert_eq!(r#""a""#, array_from_reader[0].get()); + assert_eq!(r#"42"#, array_from_reader[1].get()); + assert_eq!(r#"{"foo": "bar"}"#, array_from_reader[2].get()); + assert_eq!(r#"null"#, array_from_reader[3].get()); + + let array_to_string = serde_json::to_string(&array_from_str).unwrap(); + assert_eq!(r#"["a",42,{"foo": "bar"},null]"#, array_to_string); +}