Repository: serde-rs/json (language: rust)

Issue:
Add a RawValue type
It would be helpful to have a type similar to Go's [`json.RawMessage`](https://golang.org/pkg/encoding/json/#RawMessage) that is not tokenized during deserialization, but rather its raw contents stored as a `Vec<u8>` or `&'de [u8]`.

The following pseudo-code demonstrates the idea.
```rust
#[derive(Deserialize)]
struct Struct {
    /// Deserialized normally.
    core_data: Vec<i32>,

    /// Contents of `user_data` are copied / borrowed directly from the input
    /// with no modification.
    ///
    /// `RawValue<'static>` is akin to `Vec<u8>`.
    /// `RawValue<'a>` is akin to `&'a [u8]`.
    user_data: serde_json::RawValue<'static>,
}

fn main() {
    let json = r#"
    {
        "core_data": [1, 2, 3],
        "user_data": { "foo": {}, "bar": 123, "baz": "abc" }
    }
    "#;
    
    let s: Struct = serde_json::from_bytes(&json).unwrap();
    println!("{}", s.user_data); // "{ \"foo\": {}, \"bar\": 123, \"baz\": \"abc\" }"
}
```

The main advantage of this is would be to have 'lazily-deserialized' values.


Discussion / hints:
@dtolnay mentions that the work happening in #416 might lay some groundwork for such a change to take place.
Yeah, this sounds useful. Ideally we could get some of the building blocks for this sort of thing (custom 'built-in' types) integrated into serde itself, in time.
I need this for a project I'm working on, and would be happy to give it shot following the same approach as #416. Is this something that you'd accept a PR for?
Yes I would like a PR for this. When you say you need this feature, is it because deserializing to serde_json::Value is too slow in your project and you are expecting this to have better performance, or some other reason?
Yeah, I've got an http web server that's backed by a postgres database which stores JSONB values, and would like to shuffle data back and forth (and embed into other payloads) with as few allocations as possible.
As a first step, please put together a short benchmark that you trust as reasonably representative of the shuffling data back and forth piece of your application. Ideally it would depend on serde / serde_derive / serde_json but nothing else -- so no postgres or http stuff. Focus on the data structures so that they have the same ratio and pattern of raw vs meaningful content as your real use case. Write it using serde_json::Value for now, and then the goal will be to swap in a raw value once it's implemented and observe a speedup.
Wrote a small microbenchmark here: https://gist.github.com/srijs/7fe21b43c2cf5d2ceeb593ae4591c6f5

Please let me know if this is what you had in mind!
:+1: looks good, let's make it work.

Fix patch:
diff --git a/src/de.rs b/src/de.rs
index f1c5c3cff..0ad91a2a8 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -8,6 +8,7 @@
 
 //! Deserialize JSON data to a Rust data structure.
 
+use std::borrow::Cow;
 use std::io;
 use std::marker::PhantomData;
 use std::result;
@@ -946,6 +947,22 @@ impl<'de, R: Read<'de>> Deserializer<R> {
             }
         }
     }
+
+    fn deserialize_raw_value<V>(&mut self, visitor: V) -> Result<V::Value>
+    where
+        V: de::Visitor<'de>,
+    {
+        if let None = try!(self.parse_whitespace()) {
+            return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
+        }
+
+        self.read.toggle_raw_buffering();
+        de::Deserializer::deserialize_any(&mut *self, de::IgnoredAny)?;
+        match self.read.toggle_raw_buffering().unwrap() {
+            Cow::Owned(byte_buf) => visitor.visit_byte_buf(byte_buf),
+            Cow::Borrowed(bytes) => visitor.visit_borrowed_bytes(bytes),
+        }
+    }
 }
 
 impl FromStr for Number {
@@ -1412,10 +1429,14 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
 
     /// Parses a newtype struct as the underlying value.
     #[inline]
-    fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value>
+    fn deserialize_newtype_struct<V>(self, name: &str, visitor: V) -> Result<V::Value>
     where
         V: de::Visitor<'de>,
     {
+        if name == ::raw::SERDE_STRUCT_NAME {
+            return self.deserialize_raw_value(visitor);
+        }
+
         visitor.visit_newtype_struct(self)
     }
 
diff --git a/src/lib.rs b/src/lib.rs
index d9b79175e..e0b7a0b77 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -364,7 +364,7 @@ pub use self::ser::{
     to_string, to_string_pretty, to_vec, to_vec_pretty, to_writer, to_writer_pretty, Serializer,
 };
 #[doc(inline)]
-pub use self::value::{from_value, to_value, Map, Number, Value};
+pub use self::value::{from_value, to_value, Map, Number, RawValue, Value};
 
 // We only use our own error type; no need for From conversions provided by the
 // standard library's try! macro. This reduces lines of LLVM IR by 4%.
@@ -388,4 +388,5 @@ pub mod value;
 
 mod iter;
 mod number;
+mod raw;
 mod read;
diff --git a/src/raw.rs b/src/raw.rs
new file mode 100644
index 000000000..74d2c7a00
--- /dev/null
+++ b/src/raw.rs
@@ -0,0 +1,93 @@
+use std::borrow::Cow;
+use std::fmt;
+
+use serde::de::Visitor;
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
+
+/// Represents any valid JSON value as a series of raw bytes.
+///
+/// This type can be used to defer parsing parts of a payload until later,
+/// or to embed it verbatim into another JSON payload.
+///
+/// When serializing, a value of this type will retain its original formatting
+/// and will not be minified or pretty-printed.
+///
+/// When deserializing, this type can not be used with the `#[serde(flatten)]` attribute,
+/// as it relies on the original input buffer.
+
+#[derive(Debug, Clone, PartialEq)]
+pub struct RawValue<'a>(Cow<'a, str>);
+
+impl<'a> AsRef<str> for RawValue<'a> {
+    fn as_ref(&self) -> &str {
+        &self.0
+    }
+}
+
+impl<'a> fmt::Display for RawValue<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(&self.0)
+    }
+}
+
+/// Not public API. Should be pub(crate).
+#[doc(hidden)]
+pub const SERDE_STRUCT_NAME: &'static str = "$__serde_private_RawValue";
+
+impl<'a> Serialize for RawValue<'a> {
+    #[inline]
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        serializer.serialize_newtype_struct(SERDE_STRUCT_NAME, &self.0)
+    }
+}
+
+impl<'a, 'de> Deserialize<'de> for RawValue<'a>
+where
+    'de: 'a,
+{
+    #[inline]
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        struct RawValueVisitor;
+
+        impl<'de> Visitor<'de> for RawValueVisitor {
+            type Value = RawValue<'de>;
+
+            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+                write!(formatter, "a deserializable RawValue")
+            }
+
+            fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
+            where
+                E: ::serde::de::Error,
+            {
+                Ok(RawValue(Cow::Owned(s)))
+            }
+
+            fn visit_byte_buf<E>(self, b: Vec<u8>) -> Result<Self::Value, E>
+            where
+                E: ::serde::de::Error,
+            {
+                String::from_utf8(b)
+                    .map(|s| RawValue(Cow::Owned(s)))
+                    .map_err(|err| ::serde::de::Error::custom(err))
+            }
+
+            fn visit_borrowed_bytes<E>(self, b: &'de [u8]) -> Result<Self::Value, E>
+            where
+                E: ::serde::de::Error,
+            {
+                ::std::str::from_utf8(b)
+                    .map(|s| RawValue(Cow::Borrowed(s)))
+                    .map_err(|err| ::serde::de::Error::custom(err))
+            }
+        }
+
+        deserializer.deserialize_newtype_struct(SERDE_STRUCT_NAME, RawValueVisitor)
+    }
+}
diff --git a/src/read.rs b/src/read.rs
index f2cc9f93b..8084f40ba 100644
--- a/src/read.rs
+++ b/src/read.rs
@@ -6,6 +6,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::borrow::Cow;
 use std::ops::Deref;
 use std::{char, cmp, io, str};
 
@@ -76,6 +77,13 @@ 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/off. When switching off, returns a copy-on-write
+    /// buffer with the captured data.
+    ///
+    /// This is used to deserialize `RawValue`.
+    #[doc(hidden)]
+    fn toggle_raw_buffering(&mut self) -> Option<Cow<'de, [u8]>>;
 }
 
 pub struct Position {
@@ -107,6 +115,7 @@ where
     iter: LineColIterator<io::Bytes<R>>,
     /// Temporary storage of peeked byte.
     ch: Option<u8>,
+    raw_buffer: Option<Vec<u8>>,
 }
 
 /// JSON input source that reads from a slice of bytes.
@@ -117,6 +126,7 @@ pub struct SliceRead<'a> {
     slice: &'a [u8],
     /// Index of the *next* byte that will be returned by next() or peek().
     index: usize,
+    raw_buffering_start_index: Option<usize>,
 }
 
 /// JSON input source that reads from a UTF-8 string.
@@ -142,6 +152,7 @@ where
         IoRead {
             iter: LineColIterator::new(reader.bytes()),
             ch: None,
+            raw_buffer: None,
         }
     }
 }
@@ -193,10 +204,20 @@ where
     #[inline]
     fn next(&mut self) -> io::Result<Option<u8>> {
         match self.ch.take() {
-            Some(ch) => Ok(Some(ch)),
+            Some(ch) => {
+                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)) => {
+                    if let Some(ref mut buf) = self.raw_buffer {
+                        buf.push(ch);
+                    }
+                    Ok(Some(ch))
+                }
                 None => Ok(None),
             },
         }
@@ -219,7 +240,11 @@ where
 
     #[inline]
     fn discard(&mut self) {
-        self.ch = None;
+        if let Some(ch) = self.ch.take() {
+            if let Some(ref mut buf) = self.raw_buffer {
+                buf.push(ch);
+            }
+        }
     }
 
     fn position(&self) -> Position {
@@ -274,6 +299,15 @@ where
             }
         }
     }
+
+    fn toggle_raw_buffering(&mut self) -> Option<Cow<'de, [u8]>> {
+        if let Some(buffer) = self.raw_buffer.take() {
+            Some(Cow::Owned(buffer))
+        } else {
+            self.raw_buffer = Some(Vec::new());
+            None
+        }
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -284,6 +318,7 @@ impl<'a> SliceRead<'a> {
         SliceRead {
             slice: slice,
             index: 0,
+            raw_buffering_start_index: None,
         }
     }
 
@@ -437,6 +472,15 @@ impl<'a> Read<'a> for SliceRead<'a> {
             }
         }
     }
+
+    fn toggle_raw_buffering(&mut self) -> Option<Cow<'a, [u8]>> {
+        if let Some(start_index) = self.raw_buffering_start_index.take() {
+            Some(Cow::Borrowed(&self.slice[start_index..self.index]))
+        } else {
+            self.raw_buffering_start_index = Some(self.index);
+            None
+        }
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -498,6 +542,10 @@ impl<'a> Read<'a> for StrRead<'a> {
     fn ignore_str(&mut self) -> Result<()> {
         self.delegate.ignore_str()
     }
+
+    fn toggle_raw_buffering(&mut self) -> Option<Cow<'a, [u8]>> {
+        self.delegate.toggle_raw_buffering()
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/src/ser.rs b/src/ser.rs
index ca9b637ee..af53c8cae 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<W, F = CompactFormatter> {
     writer: W,
@@ -286,10 +283,14 @@ where
 
     /// Serialize newtypes without an object wrapper.
     #[inline]
-    fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> Result<()>
+    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<()>
     where
         T: ser::Serialize,
     {
+        if name == ::raw::SERDE_STRUCT_NAME {
+            return value.serialize(RawValueStrEmitter(self));
+        }
+
         value.serialize(self)
     }
 
@@ -1400,6 +1401,189 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W,
     }
 }
 
+struct RawValueStrEmitter<'a, W: 'a + io::Write, F: 'a + Formatter>(&'a mut Serializer<W, F>);
+
+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<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_i8(self, _v: i8) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_i16(self, _v: i16) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_i32(self, _v: i32) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_i64(self, _v: i64) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    serde_if_integer128! {
+        fn serialize_i128(self, _v: i128) -> Result<Self::Ok> {
+            Err(ser::Error::custom("expected RawValue"))
+        }
+    }
+
+    fn serialize_u8(self, _v: u8) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_u16(self, _v: u16) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_u32(self, _v: u32) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_u64(self, _v: u64) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    serde_if_integer128! {
+        fn serialize_u128(self, _v: u128) -> Result<Self::Ok> {
+            Err(ser::Error::custom("expected RawValue"))
+        }
+    }
+
+    fn serialize_f32(self, _v: f32) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_f64(self, _v: f64) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_char(self, _v: char) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_str(self, value: &str) -> Result<Self::Ok> {
+        let RawValueStrEmitter(serializer) = self;
+        serializer
+            .formatter
+            .write_raw_fragment(&mut serializer.writer, value)
+            .map_err(Error::io)
+    }
+
+    fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_none(self) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok>
+    where
+        T: Serialize,
+    {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_unit(self) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_unit_variant(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        _variant: &'static str,
+    ) -> Result<Self::Ok> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_newtype_struct<T: ?Sized>(
+        self,
+        _name: &'static str,
+        _value: &T,
+    ) -> Result<Self::Ok>
+    where
+        T: Serialize,
+    {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_newtype_variant<T: ?Sized>(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        _variant: &'static str,
+        _value: &T,
+    ) -> Result<Self::Ok>
+    where
+        T: Serialize,
+    {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_tuple_struct(
+        self,
+        _name: &'static str,
+        _len: usize,
+    ) -> Result<Self::SerializeTupleStruct> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_tuple_variant(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        _variant: &'static str,
+        _len: usize,
+    ) -> Result<Self::SerializeTupleVariant> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_struct_variant(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        _variant: &'static str,
+        _len: usize,
+    ) -> Result<Self::SerializeStructVariant> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+}
+
 /// Represents a character escape code in a type-safe manner.
 pub enum CharEscape {
     /// An escaped quote `"`
@@ -1743,6 +1927,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<W: ?Sized>(&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.
diff --git a/src/value/de.rs b/src/value/de.rs
index dc8dbc6be..73dfb8bce 100644
--- a/src/value/de.rs
+++ b/src/value/de.rs
@@ -300,12 +300,16 @@ impl<'de> serde::Deserializer<'de> for Value {
     #[inline]
     fn deserialize_newtype_struct<V>(
         self,
-        _name: &'static str,
+        name: &'static str,
         visitor: V,
     ) -> Result<V::Value, Self::Error>
     where
         V: Visitor<'de>,
     {
+        if name == ::raw::SERDE_STRUCT_NAME {
+            return visitor.visit_string(self.to_string());
+        }
+
         visitor.visit_newtype_struct(self)
     }
 
diff --git a/src/value/mod.rs b/src/value/mod.rs
index f5e33b457..155874a9c 100644
--- a/src/value/mod.rs
+++ b/src/value/mod.rs
@@ -118,6 +118,7 @@ use serde::ser::Serialize;
 use error::Error;
 pub use map::Map;
 pub use number::Number;
+pub use raw::RawValue;
 
 pub use self::index::Index;
 
diff --git a/src/value/ser.rs b/src/value/ser.rs
index d3f71b373..54ce18db8 100644
--- a/src/value/ser.rs
+++ b/src/value/ser.rs
@@ -6,7 +6,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use serde::ser::Impossible;
+use serde::ser::{self, Impossible};
 use serde::{self, Serialize};
 
 use error::{Error, ErrorCode};
@@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -150,12 +147,16 @@ impl serde::Serializer for Serializer {
     #[inline]
     fn serialize_newtype_struct<T: ?Sized>(
         self,
-        _name: &'static str,
+        name: &'static str,
         value: &T,
     ) -> Result<Value, Error>
     where
         T: Serialize,
     {
+        if name == ::raw::SERDE_STRUCT_NAME {
+            return value.serialize(RawValueEmitter);
+        }
+
         value.serialize(self)
     }
 
@@ -812,3 +813,186 @@ impl ser::Serializer for NumberValueEmitter {
         Err(invalid_number())
     }
 }
+
+struct RawValueEmitter;
+
+impl ser::Serializer for RawValueEmitter {
+    type Ok = Value;
+    type Error = Error;
+
+    type SerializeSeq = Impossible<Value, Error>;
+    type SerializeTuple = Impossible<Value, Error>;
+    type SerializeTupleStruct = Impossible<Value, Error>;
+    type SerializeTupleVariant = Impossible<Value, Error>;
+    type SerializeMap = Impossible<Value, Error>;
+    type SerializeStruct = Impossible<Value, Error>;
+    type SerializeStructVariant = Impossible<Value, Error>;
+
+    fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    serde_if_integer128! {
+        fn serialize_i128(self, _v: i128) -> Result<Self::Ok, Self::Error> {
+            Err(ser::Error::custom("expected RawValue"))
+        }
+    }
+
+    fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    serde_if_integer128! {
+        fn serialize_u128(self, _v: u128) -> Result<Self::Ok, Self::Error> {
+            Err(ser::Error::custom("expected RawValue"))
+        }
+    }
+
+    fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error> {
+        ::from_str(value)
+    }
+
+    fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error>
+    where
+        T: Serialize,
+    {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_unit_variant(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        _variant: &'static str,
+    ) -> Result<Self::Ok, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_newtype_struct<T: ?Sized>(
+        self,
+        _name: &'static str,
+        _value: &T,
+    ) -> Result<Self::Ok, Self::Error>
+    where
+        T: Serialize,
+    {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_newtype_variant<T: ?Sized>(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        _variant: &'static str,
+        _value: &T,
+    ) -> Result<Self::Ok, Self::Error>
+    where
+        T: Serialize,
+    {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_tuple_struct(
+        self,
+        _name: &'static str,
+        _len: usize,
+    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_tuple_variant(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        _variant: &'static str,
+        _len: usize,
+    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_struct(
+        self,
+        _name: &'static str,
+        _len: usize,
+    ) -> Result<Self::SerializeStruct, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+
+    fn serialize_struct_variant(
+        self,
+        _name: &'static str,
+        _variant_index: u32,
+        _variant: &'static str,
+        _len: usize,
+    ) -> Result<Self::SerializeStructVariant, Self::Error> {
+        Err(ser::Error::custom("expected RawValue"))
+    }
+}


Test patch:
diff --git a/tests/test.rs b/tests/test.rs
index 08d038837..09c51a62d 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -44,7 +44,7 @@ use serde_bytes::{ByteBuf, Bytes};
 
 use serde_json::{
     from_reader, from_slice, from_str, from_value, to_string, to_string_pretty, to_value, to_vec,
-    to_writer, Deserializer, Number, Value,
+    to_writer, Deserializer, Number, RawValue, Value,
 };
 
 macro_rules! treemap {
@@ -2039,3 +2039,52 @@ fn test_integer128() {
         ),
     ]);
 }
+
+#[test]
+fn test_raw_value() {
+    #[derive(Serialize, Deserialize)]
+    struct Wrapper<'a> {
+        a: i8,
+        #[serde(borrow)]
+        b: RawValue<'a>,
+        c: i8,
+    };
+
+    let wrapper_from_str =
+        serde_json::from_str::<Wrapper>(r#"{"a": 1, "b": {"foo": 2}, "c": 3}"#).unwrap();
+    assert_eq!(r#"{"foo": 2}"#, wrapper_from_str.b.as_ref());
+
+    let wrapper_from_reader = serde_json::from_reader::<_, Wrapper<'static>>(
+        br#"{"a": 1, "b": {"foo": 2}, "c": 3}"#.as_ref(),
+    ).unwrap();
+    assert_eq!(r#"{"foo": 2}"#, wrapper_from_reader.b.as_ref());
+
+    let wrapper_from_value =
+        serde_json::from_value::<Wrapper<'static>>(json!({"a": 1, "b": {"foo": 2}, "c": 3}))
+            .unwrap();
+    assert_eq!(r#"{"foo":2}"#, wrapper_from_value.b.as_ref());
+
+    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 =
+        serde_json::from_str::<Vec<RawValue>>(r#"["a", 42, {"foo": "bar"}, null]"#).unwrap();
+    assert_eq!(r#""a""#, array_from_str[0].as_ref());
+    assert_eq!(r#"42"#, array_from_str[1].as_ref());
+    assert_eq!(r#"{"foo": "bar"}"#, array_from_str[2].as_ref());
+    assert_eq!(r#"null"#, array_from_str[3].as_ref());
+
+    let array_from_reader = serde_json::from_reader::<_, Vec<RawValue<'static>>>(
+        br#"["a", 42, {"foo": "bar"}, null]"#.as_ref(),
+    ).unwrap();
+    assert_eq!(r#""a""#, array_from_reader[0].as_ref());
+    assert_eq!(r#"42"#, array_from_reader[1].as_ref());
+    assert_eq!(r#"{"foo": "bar"}"#, array_from_reader[2].as_ref());
+    assert_eq!(r#"null"#, array_from_reader[3].as_ref());
+
+    let array_to_string = serde_json::to_string(&array_from_str).unwrap();
+    assert_eq!(r#"["a",42,{"foo": "bar"},null]"#, array_to_string);
+}