From 2d3a0d6038a835af7917e11bdcd4e9dcfa8a52ec Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 7 Mar 2021 22:11:39 +0000 Subject: [PATCH] json method receives plain serialize (#2052) --- actix-http/CHANGES.md | 2 ++ actix-http/src/response.rs | 16 ++++++++-------- src/data.rs | 13 +++++++++++++ src/types/form.rs | 12 ++++++++++++ src/types/json.rs | 12 ++++++++++++ 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 165b004a6..14218289d 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -4,6 +4,7 @@ ### Changed * Feature `cookies` is now optional and disabled by default. [#1981] * `ws::hash_key` now returns array. [#2035] +* `ResponseBuilder::json` now takes `impl Serialize`. [#2052] ### Removed * re-export of `futures_channel::oneshot::Canceled` is removed from `error` mod. [#1994] @@ -12,6 +13,7 @@ [#1981]: https://github.com/actix/actix-web/pull/1981 [#1994]: https://github.com/actix/actix-web/pull/1994 [#2035]: https://github.com/actix/actix-web/pull/2035 +[#2052]: https://github.com/actix/actix-web/pull/2052 ## 3.0.0-beta.3 - 2021-02-10 diff --git a/actix-http/src/response.rs b/actix-http/src/response.rs index c5a4aec13..d581fd293 100644 --- a/actix-http/src/response.rs +++ b/actix-http/src/response.rs @@ -5,7 +5,6 @@ use std::{ convert::TryInto, fmt, future::Future, - ops, pin::Pin, str, task::{Context, Poll}, @@ -673,12 +672,8 @@ impl ResponseBuilder { /// Set a json body and generate `Response` /// /// `ResponseBuilder` can not be used after this call. - pub fn json(&mut self, value: T) -> Response - where - T: ops::Deref, - T::Target: Serialize, - { - match serde_json::to_string(&*value) { + pub fn json(&mut self, value: impl Serialize) -> Response { + match serde_json::to_string(&value) { Ok(body) => { let contains = if let Some(parts) = parts(&mut self.head, &self.err) { parts.headers.contains_key(header::CONTENT_TYPE) @@ -1007,7 +1002,12 @@ mod tests { #[test] fn test_json() { - let resp = Response::build(StatusCode::OK).json(vec!["v1", "v2", "v3"]); + let resp = Response::Ok().json(vec!["v1", "v2", "v3"]); + let ct = resp.headers().get(CONTENT_TYPE).unwrap(); + assert_eq!(ct, HeaderValue::from_static("application/json")); + assert_eq!(resp.body().get_ref(), b"[\"v1\",\"v2\",\"v3\"]"); + + let resp = Response::Ok().json(&["v1", "v2", "v3"]); let ct = resp.headers().get(CONTENT_TYPE).unwrap(); assert_eq!(ct, HeaderValue::from_static("application/json")); assert_eq!(resp.body().get_ref(), b"[\"v1\",\"v2\",\"v3\"]"); diff --git a/src/data.rs b/src/data.rs index 133248212..0336553ca 100644 --- a/src/data.rs +++ b/src/data.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use actix_http::error::{Error, ErrorInternalServerError}; use actix_http::Extensions; use futures_util::future::{err, ok, LocalBoxFuture, Ready}; +use serde::Serialize; use crate::dev::Payload; use crate::extract::FromRequest; @@ -102,6 +103,18 @@ impl From> for Data { } } +impl Serialize for Data +where + T: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.serialize(serializer) + } +} + impl FromRequest for Data { type Config = (); type Error = Error; diff --git a/src/types/form.rs b/src/types/form.rs index 4f3ecbe7c..57a742e38 100644 --- a/src/types/form.rs +++ b/src/types/form.rs @@ -106,6 +106,18 @@ impl ops::DerefMut for Form { } } +impl Serialize for Form +where + T: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.serialize(serializer) + } +} + /// See [here](#extractor) for example of usage as an extractor. impl FromRequest for Form where diff --git a/src/types/json.rs b/src/types/json.rs index 866d835f2..d8ce3cb71 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -114,6 +114,18 @@ where } } +impl Serialize for Json +where + T: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.serialize(serializer) + } +} + /// Creates response with OK status code, correct content type header, and serialized JSON payload. /// /// If serialization failed