Merge into_json_deserialize into into_json.

This commit is contained in:
Jacob Hoffman-Andrews
2020-11-21 15:47:49 -08:00
parent 4cb856196e
commit 271e650662
4 changed files with 43 additions and 50 deletions

View File

@@ -25,8 +25,7 @@ pub const DEFAULT_CHARACTER_SET: &str = "utf-8";
/// ///
/// The `Response` is used to read response headers and decide what to do with the body. /// The `Response` is used to read response headers and decide what to do with the body.
/// Note that the socket connection is open and the body not read until one of /// Note that the socket connection is open and the body not read until one of
/// [`into_reader()`](#method.into_reader), [`into_json()`](#method.into_json), /// [`into_reader()`](#method.into_reader), [`into_json()`](#method.into_json), or
/// [`into_json_deserialize()`](#method.into_json_deserialize) or
/// [`into_string()`](#method.into_string) consumes the response. /// [`into_string()`](#method.into_string) consumes the response.
/// ///
/// ``` /// ```
@@ -343,47 +342,13 @@ impl Response {
} }
} }
/// Turn this response into a (serde) JSON value of the response body. /// Read the body of this response into a serde_json::Value, or any other type that
// implements the [serde::Deserialize] trait.
/// ///
/// Requires feature `ureq = { version = "*", features = ["json"] }` /// You must use either a type annotation as shown below (`message: Message`), or the
/// [turbofish operator] (`::<Type>`) so Rust knows what type you are trying to read.
/// ///
/// Example: /// [turbofish operator]: https://matematikaadit.github.io/posts/rust-turbofish.html
///
/// ```
/// # fn main() -> Result<(), ureq::Error> {
/// # ureq::is_test(true);
/// let json: serde_json::Value = ureq::get("http://example.com/hello_world.json")
/// .call()?
/// .into_json()?;
///
/// assert_eq!(json["hello"], "world");
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "json")]
pub fn into_json(self) -> io::Result<serde_json::Value> {
use crate::stream::io_err_timeout;
use std::error::Error;
let reader = self.into_reader();
serde_json::from_reader(reader).map_err(|e| {
// This is to unify TimedOut io::Error in the API.
// We make a clone of the original error since serde_json::Error doesn't
// let us get the wrapped error instance back.
if let Some(ioe) = e.source().and_then(|s| s.downcast_ref::<io::Error>()) {
if ioe.kind() == ErrorKind::TimedOut {
return io_err_timeout(ioe.to_string());
}
}
io::Error::new(
ErrorKind::InvalidData,
format!("Failed to read JSON: {}", e),
)
})
}
/// Turn the body of this response into a type that implements the [serde::Deserialize] trait.
/// ///
/// Requires feature `ureq = { version = "*", features = ["json"] }` /// Requires feature `ureq = { version = "*", features = ["json"] }`
/// ///
@@ -402,16 +367,44 @@ impl Response {
/// let message: Message = /// let message: Message =
/// ureq::get("http://example.com/hello_world.json") /// ureq::get("http://example.com/hello_world.json")
/// .call()? /// .call()?
/// .into_json_deserialize()?; /// .into_json()?;
/// ///
/// assert_eq!(message.hello, "world"); /// assert_eq!(message.hello, "world");
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
///
/// Or, if you don't want to define a struct to read your JSON into, you can
/// use the convenient `serde_json::Value` type to parse arbitrary or unknown
/// JSON.
///
/// ```
/// # fn main() -> Result<(), ureq::Error> {
/// # ureq::is_test(true);
/// let json: serde_json::Value = ureq::get("http://example.com/hello_world.json")
/// .call()?
/// .into_json()?;
///
/// assert_eq!(json["hello"], "world");
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "json")] #[cfg(feature = "json")]
pub fn into_json_deserialize<T: DeserializeOwned>(self) -> io::Result<T> { pub fn into_json<T: DeserializeOwned>(self) -> io::Result<T> {
use crate::stream::io_err_timeout;
use std::error::Error;
let reader = self.into_reader(); let reader = self.into_reader();
serde_json::from_reader(reader).map_err(|e| { serde_json::from_reader(reader).map_err(|e| {
// This is to unify TimedOut io::Error in the API.
// We make a clone of the original error since serde_json::Error doesn't
// let us get the wrapped error instance back.
if let Some(ioe) = e.source().and_then(|s| s.downcast_ref::<io::Error>()) {
if ioe.kind() == ErrorKind::TimedOut {
return io_err_timeout(ioe.to_string());
}
}
io::Error::new( io::Error::new(
ErrorKind::InvalidData, ErrorKind::InvalidData,
format!("Failed to read JSON: {}", e), format!("Failed to read JSON: {}", e),
@@ -714,7 +707,7 @@ mod tests {
\r\n\ \r\n\
{\"hello\":\"world\"}"; {\"hello\":\"world\"}";
let resp = s.parse::<Response>().unwrap(); let resp = s.parse::<Response>().unwrap();
let v = resp.into_json().unwrap(); let v: serde_json::Value = resp.into_json().unwrap();
let compare = "{\"hello\":\"world\"}" let compare = "{\"hello\":\"world\"}"
.parse::<serde_json::Value>() .parse::<serde_json::Value>()
.unwrap(); .unwrap();
@@ -735,7 +728,7 @@ mod tests {
\r\n\ \r\n\
{\"hello\":\"world\"}"; {\"hello\":\"world\"}";
let resp = s.parse::<Response>().unwrap(); let resp = s.parse::<Response>().unwrap();
let v = resp.into_json_deserialize::<Hello>().unwrap(); let v: Hello = resp.into_json::<Hello>().unwrap();
assert_eq!(v.hello, "world"); assert_eq!(v.hello, "world");
} }

View File

@@ -75,7 +75,7 @@ fn body_as_json() {
) )
}); });
let resp = get("test://host/body_as_json").call().unwrap(); let resp = get("test://host/body_as_json").call().unwrap();
let json = resp.into_json().unwrap(); let json: serde_json::Value = resp.into_json().unwrap();
assert_eq!(json["hello"], "world"); assert_eq!(json["hello"], "world");
} }
@@ -98,7 +98,7 @@ fn body_as_json_deserialize() {
) )
}); });
let resp = get("test://host/body_as_json_deserialize").call().unwrap(); let resp = get("test://host/body_as_json_deserialize").call().unwrap();
let json = resp.into_json_deserialize::<Hello>().unwrap(); let json: Hello = resp.into_json().unwrap();
assert_eq!(json.hello, "world"); assert_eq!(json.hello, "world");
} }

View File

@@ -138,9 +138,9 @@ fn overall_timeout_reading_json() {
let timeout = Duration::from_millis(500); let timeout = Duration::from_millis(500);
let agent = builder().timeout(timeout).build(); let agent = builder().timeout(timeout).build();
let resp = agent.get(&url).call().unwrap(); let result: Result<serde_json::Value, io::Error> = agent.get(&url).call().unwrap().into_json();
match resp.into_json() { match result {
Ok(_) => Err("successful response".to_string()), Ok(_) => Err("successful response".to_string()),
Err(e) => match e.kind() { Err(e) => match e.kind() {
io::ErrorKind::TimedOut => Ok(()), io::ErrorKind::TimedOut => Ok(()),

View File

@@ -18,7 +18,7 @@ fn agent_set_header() {
.call() .call()
.unwrap(); .unwrap();
assert_eq!(resp.status(), 200); assert_eq!(resp.status(), 200);
let json = resp.into_json_deserialize::<HttpBin>().unwrap(); let json: HttpBin = resp.into_json().unwrap();
// println!("{:?}", json); // println!("{:?}", json);
assert_eq!("value", json.headers.get("Header").unwrap()); assert_eq!("value", json.headers.get("Header").unwrap());
} }