Make Response::into_json deserialize into a serde DeserializeOwned
This removes the necessity to take the result of Response::into_json and having to convert it into a struct by using serde_json::from_value This adds no new dependencies since serde_json already depends on serde. Users of ureq will have to include `serde_derive` either by importing it directly or by using serde with the `derive` feature, unless they want to manually implement `Deserialize` on their structs.
This commit is contained in:
committed by
Martin Algesten
parent
8f2d094cef
commit
0b69c595b6
@@ -15,7 +15,7 @@ all-features = true
|
||||
|
||||
[features]
|
||||
default = ["tls", "cookies"]
|
||||
json = ["serde_json"]
|
||||
json = ["serde", "serde_json"]
|
||||
charset = ["encoding"]
|
||||
tls = ["rustls", "webpki", "webpki-roots"]
|
||||
native-certs = ["rustls-native-certs"]
|
||||
@@ -34,5 +34,9 @@ rustls = { version = "0.17", optional = true, features = [] }
|
||||
webpki = { version = "0.21", optional = true }
|
||||
webpki-roots = { version = "0.19", optional = true }
|
||||
rustls-native-certs = { version = "0.3", optional = true }
|
||||
serde = { version = "1", optional = true }
|
||||
serde_json = { version = "1", optional = true }
|
||||
encoding = { version = "0.2", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
@@ -10,8 +10,6 @@ use encoding::EncoderTrap;
|
||||
|
||||
#[cfg(feature = "json")]
|
||||
use super::SerdeValue;
|
||||
#[cfg(feature = "json")]
|
||||
use serde_json;
|
||||
|
||||
/// The different kinds of bodies to send.
|
||||
///
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::stream::Stream;
|
||||
use crate::unit::Unit;
|
||||
|
||||
#[cfg(feature = "json")]
|
||||
use serde_json;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
#[cfg(feature = "charset")]
|
||||
use encoding::label::encoding_from_whatwg_label;
|
||||
@@ -382,16 +382,23 @@ impl Response {
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// # use serde::Deserialize;
|
||||
///
|
||||
/// #[derive(Deserialize)]
|
||||
/// struct Hello {
|
||||
/// hello: String,
|
||||
/// }
|
||||
///
|
||||
/// let resp =
|
||||
/// ureq::get("https://ureq.s3.eu-central-1.amazonaws.com/hello_world.json")
|
||||
/// .call();
|
||||
///
|
||||
/// let json = resp.into_json().unwrap();
|
||||
/// let json = resp.into_json::<Hello>().unwrap();
|
||||
///
|
||||
/// assert_eq!(json["hello"], "world");
|
||||
/// assert_eq!(json.hello, "world");
|
||||
/// ```
|
||||
#[cfg(feature = "json")]
|
||||
pub fn into_json(self) -> IoResult<serde_json::Value> {
|
||||
pub fn into_json<T: DeserializeOwned>(self) -> IoResult<T> {
|
||||
let reader = self.into_reader();
|
||||
serde_json::from_reader(reader).map_err(|e| {
|
||||
IoError::new(
|
||||
@@ -723,15 +730,19 @@ mod tests {
|
||||
#[test]
|
||||
#[cfg(feature = "json")]
|
||||
fn parse_simple_json() {
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Hello {
|
||||
hello: String,
|
||||
}
|
||||
|
||||
let s = "HTTP/1.1 200 OK\r\n\
|
||||
\r\n\
|
||||
{\"hello\":\"world\"}";
|
||||
let resp = s.parse::<Response>().unwrap();
|
||||
let v = resp.into_json().unwrap();
|
||||
let compare = "{\"hello\":\"world\"}"
|
||||
.parse::<serde_json::Value>()
|
||||
.unwrap();
|
||||
assert_eq!(v, compare);
|
||||
let v = resp.into_json::<Hello>().unwrap();
|
||||
assert_eq!(v.hello, "world");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -61,6 +61,13 @@ fn body_as_text() {
|
||||
#[test]
|
||||
#[cfg(feature = "json")]
|
||||
fn body_as_json() {
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Hello {
|
||||
hello: String,
|
||||
}
|
||||
|
||||
test::set_handler("/body_as_json", |_unit| {
|
||||
test::make_response(
|
||||
200,
|
||||
@@ -70,8 +77,8 @@ fn body_as_json() {
|
||||
)
|
||||
});
|
||||
let resp = get("test://host/body_as_json").call();
|
||||
let json = resp.into_json().unwrap();
|
||||
assert_eq!(json["hello"], "world");
|
||||
let json = resp.into_json::<Hello>().unwrap();
|
||||
assert_eq!(json.hello, "world");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -17,6 +17,14 @@ fn tls_connection_close() {
|
||||
#[cfg(feature = "json")]
|
||||
#[test]
|
||||
fn agent_set_cookie() {
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct HttpBin {
|
||||
headers: HashMap<String, String>,
|
||||
}
|
||||
|
||||
let agent = ureq::Agent::default().build();
|
||||
let cookie = ureq::Cookie::build("name", "value")
|
||||
.domain("httpbin.org")
|
||||
@@ -30,10 +38,9 @@ fn agent_set_cookie() {
|
||||
assert_eq!(resp.status(), 200);
|
||||
assert_eq!(
|
||||
"name=value",
|
||||
resp.into_json()
|
||||
.unwrap()
|
||||
.get("headers")
|
||||
resp.into_json::<HttpBin>()
|
||||
.unwrap()
|
||||
.headers
|
||||
.get("Cookie")
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user