Make json an optional feature (default off)

This commit is contained in:
Constantin Nickel
2019-09-27 16:09:25 +02:00
committed by Sean McArthur
parent a787fc1b38
commit 24394364eb
10 changed files with 59 additions and 3 deletions

View File

@@ -15,5 +15,5 @@ install:
- cargo -vV - cargo -vV
build: false build: false
test_script: test_script:
- cargo test --features blocking,gzip -- --test-threads=1 - cargo test --features blocking,gzip,json -- --test-threads=1
skip_branch_with_pr: true skip_branch_with_pr: true

View File

@@ -42,6 +42,11 @@ matrix:
- rust: nightly - rust: nightly
env: FEATURES="--features gzip" env: FEATURES="--features gzip"
# optional json
#- rust: stable
- rust: nightly
env: FEATURES="--features json"
# socks # socks
#- rust: stable #- rust: stable
#- rust: nightly #- rust: nightly

View File

@@ -33,6 +33,8 @@ cookies = ["cookie_crate", "cookie_store"]
gzip = ["async-compression"] gzip = ["async-compression"]
json = ["serde_json"]
#trust-dns = ["trust-dns-resolver"] #trust-dns = ["trust-dns-resolver"]
[dependencies] [dependencies]
@@ -59,7 +61,6 @@ time = "0.1.42"
# TODO: candidates for optional features # TODO: candidates for optional features
serde = "1.0" serde = "1.0"
serde_json = "1.0"
serde_urlencoded = "0.6.1" serde_urlencoded = "0.6.1"
# Optional deps... # Optional deps...
@@ -85,6 +86,9 @@ cookie_store = { version = "0.9", optional = true }
## gzip ## gzip
async-compression = { version = "0.1.0-alpha.4", default-features = false, features = ["gzip", "stream"], optional = true } async-compression = { version = "0.1.0-alpha.4", default-features = false, features = ["gzip", "stream"], optional = true }
## json
serde_json = { version = "1.0", optional = true }
## socks ## socks
#socks = { version = "0.3.2", optional = true } #socks = { version = "0.3.2", optional = true }
@@ -123,6 +127,16 @@ name = "blocking"
path = "examples/blocking.rs" path = "examples/blocking.rs"
required-features = ["blocking"] required-features = ["blocking"]
[[example]]
name = "json_dynamic"
path = "examples/json_dynamic.rs"
required-features = ["json"]
[[example]]
name = "json_typed"
path = "examples/json_typed.rs"
required-features = ["json"]
[[test]] [[test]]
name = "blocking" name = "blocking"
path = "tests/blocking.rs" path = "tests/blocking.rs"

View File

@@ -3,6 +3,7 @@ use std::future::Future;
use base64::encode; use base64::encode;
use serde::Serialize; use serde::Serialize;
#[cfg(feature = "json")]
use serde_json; use serde_json;
use serde_urlencoded; use serde_urlencoded;
@@ -287,10 +288,15 @@ impl RequestBuilder {
/// Send a JSON body. /// Send a JSON body.
/// ///
/// # Optional
///
/// This requires the optional `json` feature enabled.
///
/// # Errors /// # Errors
/// ///
/// Serialization can fail if `T`'s implementation of `Serialize` decides to /// Serialization can fail if `T`'s implementation of `Serialize` decides to
/// fail, or if `T` contains a map with non-string keys. /// fail, or if `T` contains a map with non-string keys.
#[cfg(feature = "json")]
pub fn json<T: Serialize + ?Sized>(mut self, json: &T) -> RequestBuilder { pub fn json<T: Serialize + ?Sized>(mut self, json: &T) -> RequestBuilder {
let mut error = None; let mut error = None;
if let Ok(ref mut req) = self.request { if let Ok(ref mut req) = self.request {

View File

@@ -11,7 +11,9 @@ use hyper::header::CONTENT_LENGTH;
use hyper::{HeaderMap, StatusCode, Version}; use hyper::{HeaderMap, StatusCode, Version};
use log::debug; use log::debug;
use mime::Mime; use mime::Mime;
#[cfg(feature = "json")]
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
#[cfg(feature = "json")]
use serde_json; use serde_json;
use tokio::timer::Delay; use tokio::timer::Delay;
use url::Url; use url::Url;
@@ -197,6 +199,10 @@ impl Response {
/// Try to deserialize the response body as JSON. /// Try to deserialize the response body as JSON.
/// ///
/// # Optional
///
/// This requires the optional `json` feature enabled.
///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
@@ -229,7 +235,9 @@ impl Response {
/// This method fails whenever the response body is not in JSON format /// This method fails whenever the response body is not in JSON format
/// or it cannot be properly deserialized to target type `T`. For more /// or it cannot be properly deserialized to target type `T`. For more
/// details please see [`serde_json::from_reader`]. /// details please see [`serde_json::from_reader`].
///
/// [`serde_json::from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html /// [`serde_json::from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html
#[cfg(feature = "json")]
pub async fn json<T: DeserializeOwned>(self) -> crate::Result<T> { pub async fn json<T: DeserializeOwned>(self) -> crate::Result<T> {
let full = self.bytes().await?; let full = self.bytes().await?;

View File

@@ -3,6 +3,7 @@ use std::fmt;
use base64::encode; use base64::encode;
use http::HttpTryFrom; use http::HttpTryFrom;
use serde::Serialize; use serde::Serialize;
#[cfg(feature = "json")]
use serde_json; use serde_json;
use serde_urlencoded; use serde_urlencoded;
@@ -388,6 +389,12 @@ impl RequestBuilder {
/// Sets the body to the JSON serialization of the passed value, and /// Sets the body to the JSON serialization of the passed value, and
/// also sets the `Content-Type: application/json` header. /// also sets the `Content-Type: application/json` header.
/// ///
/// # Optional
///
/// This requires the optional `json` feature enabled.
///
/// # Examples
///
/// ```rust /// ```rust
/// # use reqwest::Error; /// # use reqwest::Error;
/// # use std::collections::HashMap; /// # use std::collections::HashMap;
@@ -408,6 +415,7 @@ impl RequestBuilder {
/// ///
/// Serialization can fail if `T`'s implementation of `Serialize` decides to /// Serialization can fail if `T`'s implementation of `Serialize` decides to
/// fail, or if `T` contains a map with non-string keys. /// fail, or if `T` contains a map with non-string keys.
#[cfg(feature = "json")]
pub fn json<T: Serialize + ?Sized>(mut self, json: &T) -> RequestBuilder { pub fn json<T: Serialize + ?Sized>(mut self, json: &T) -> RequestBuilder {
let mut error = None; let mut error = None;
if let Ok(ref mut req) = self.request { if let Ok(ref mut req) = self.request {
@@ -552,6 +560,7 @@ mod tests {
use crate::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE, HOST}; use crate::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE, HOST};
use crate::Method; use crate::Method;
use serde::Serialize; use serde::Serialize;
#[cfg(feature = "json")]
use serde_json; use serde_json;
use serde_urlencoded; use serde_urlencoded;
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
@@ -776,6 +785,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(feature = "json")]
fn add_json() { fn add_json() {
let client = Client::new(); let client = Client::new();
let some_url = "https://google.com/"; let some_url = "https://google.com/";
@@ -796,6 +806,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(feature = "json")]
fn add_json_fail() { fn add_json_fail() {
use serde::ser::Error as _; use serde::ser::Error as _;
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};

View File

@@ -7,6 +7,7 @@ use std::time::Duration;
use http; use http;
use hyper::header::HeaderMap; use hyper::header::HeaderMap;
#[cfg(feature = "json")]
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use super::client::KeepCoreThreadAlive; use super::client::KeepCoreThreadAlive;
@@ -50,6 +51,7 @@ impl Response {
/// Checking for general status class: /// Checking for general status class:
/// ///
/// ```rust /// ```rust
/// # #[cfg(feature = "json")]
/// # fn run() -> Result<(), Box<std::error::Error>> { /// # fn run() -> Result<(), Box<std::error::Error>> {
/// let resp = reqwest::blocking::get("http://httpbin.org/get")?; /// let resp = reqwest::blocking::get("http://httpbin.org/get")?;
/// if resp.status().is_success() { /// if resp.status().is_success() {
@@ -181,6 +183,10 @@ impl Response {
/// Try and deserialize the response body as JSON using `serde`. /// Try and deserialize the response body as JSON using `serde`.
/// ///
/// # Optional
///
/// This requires the optional `json` feature enabled.
///
/// # Examples /// # Examples
/// ///
/// ```rust /// ```rust
@@ -208,7 +214,9 @@ impl Response {
/// This method fails whenever the response body is not in JSON format /// This method fails whenever the response body is not in JSON format
/// or it cannot be properly deserialized to target type `T`. For more /// or it cannot be properly deserialized to target type `T`. For more
/// details please see [`serde_json::from_reader`]. /// details please see [`serde_json::from_reader`].
///
/// [`serde_json::from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html /// [`serde_json::from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html
#[cfg(feature = "json")]
pub fn json<T: DeserializeOwned>(self) -> crate::Result<T> { pub fn json<T: DeserializeOwned>(self) -> crate::Result<T> {
wait::timeout(self.inner.json(), self.timeout).map_err(|e| match e { wait::timeout(self.inner.json(), self.timeout).map_err(|e| match e {
wait::Waited::TimedOut(e) => crate::error::decode(e), wait::Waited::TimedOut(e) => crate::error::decode(e),

View File

@@ -95,12 +95,13 @@
//! //!
//! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in //! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in
//! a similar fashion the `form` method. It can take any value that can be //! a similar fashion the `form` method. It can take any value that can be
//! serialized into JSON. //! serialized into JSON. The feature `json` is required.
//! //!
//! ```rust //! ```rust
//! # use reqwest::Error; //! # use reqwest::Error;
//! # use std::collections::HashMap; //! # use std::collections::HashMap;
//! # //! #
//! # #[cfg(feature = "json")]
//! # async fn run() -> Result<(), Error> { //! # async fn run() -> Result<(), Error> {
//! // This will POST a body of `{"lang":"rust","body":"json"}` //! // This will POST a body of `{"lang":"rust","body":"json"}`
//! let mut map = HashMap::new(); //! let mut map = HashMap::new();
@@ -159,6 +160,7 @@
//! - **blocking**: Provides the [blocking][] client API. //! - **blocking**: Provides the [blocking][] client API.
//! - **cookies**: Provides cookie session support. //! - **cookies**: Provides cookie session support.
//! - **gzip**: Provides response body gzip decompression. //! - **gzip**: Provides response body gzip decompression.
//! - **json**: Provides serialization and deserialization for JSON bodies.
//! //!
//! //!
//! [hyper]: http://hyper.rs //! [hyper]: http://hyper.rs

View File

@@ -38,6 +38,7 @@ fn test_response_non_utf_8_text() {
} }
#[test] #[test]
#[cfg(feature = "json")]
fn test_response_json() { fn test_response_json() {
let server = server::http(move |_req| async { http::Response::new("\"Hello\"".into()) }); let server = server::http(move |_req| async { http::Response::new("\"Hello\"".into()) });

View File

@@ -45,6 +45,7 @@ async fn response_text() {
} }
#[tokio::test] #[tokio::test]
#[cfg(feature = "json")]
async fn response_json() { async fn response_json() {
let _ = env_logger::try_init(); let _ = env_logger::try_init();