From fdad97aa083c1c6a76eb577173b1118b2ccfa3a1 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Sat, 15 Aug 2020 01:46:23 +0200 Subject: [PATCH] fix(juniper_graphql_ws): correct null deserialization issue (#738) Closes #735 --- juniper_graphql_ws/CHANGELOG.md | 1 + juniper_graphql_ws/src/client_message.rs | 21 +++++++++++++++++++-- juniper_graphql_ws/src/lib.rs | 2 ++ juniper_graphql_ws/src/utils.rs | 9 +++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 juniper_graphql_ws/src/utils.rs diff --git a/juniper_graphql_ws/CHANGELOG.md b/juniper_graphql_ws/CHANGELOG.md index 052324725..51a7a654c 100644 --- a/juniper_graphql_ws/CHANGELOG.md +++ b/juniper_graphql_ws/CHANGELOG.md @@ -1,3 +1,4 @@ # master +- Fix null deserialization issue ([#735](https://github.com/graphql-rust/juniper/issues/735)) - Initial Release diff --git a/juniper_graphql_ws/src/client_message.rs b/juniper_graphql_ws/src/client_message.rs index 1e20caef1..8d8268192 100644 --- a/juniper_graphql_ws/src/client_message.rs +++ b/juniper_graphql_ws/src/client_message.rs @@ -1,3 +1,4 @@ +use crate::utils::default_for_null; use juniper::{ScalarValue, Variables}; /// The payload for a client's "start" message. This triggers execution of a query, mutation, or @@ -10,7 +11,7 @@ pub struct StartPayload { pub query: String, /// The optional variables. - #[serde(default)] + #[serde(default, deserialize_with = "default_for_null")] pub variables: Variables, /// The optional operation name (required if the document contains multiple operations). @@ -27,7 +28,7 @@ pub enum ClientMessage { ConnectionInit { /// Optional parameters of any type sent from the client. These are often used for /// authentication. - #[serde(default)] + #[serde(default, deserialize_with = "default_for_null")] payload: Variables, }, /// Start messages are used to execute a GraphQL operation. @@ -128,4 +129,20 @@ mod test { serde_json::from_str(r##"{"type": "connection_terminate"}"##).unwrap(), ); } + + #[test] + fn test_deserialization_of_null() -> serde_json::Result<()> { + let payload = r#"{"query":"query","variables":null}"#; + let payload: StartPayload = serde_json::from_str(payload)?; + + let expected = StartPayload { + query: "query".into(), + variables: Variables::default(), + operation_name: None, + }; + + assert_eq!(expected, payload); + + Ok(()) + } } diff --git a/juniper_graphql_ws/src/lib.rs b/juniper_graphql_ws/src/lib.rs index 7cf73eecb..fbbb7565e 100644 --- a/juniper_graphql_ws/src/lib.rs +++ b/juniper_graphql_ws/src/lib.rs @@ -21,6 +21,8 @@ pub use server_message::*; mod schema; pub use schema::*; +mod utils; + use juniper::{ futures::{ channel::oneshot, diff --git a/juniper_graphql_ws/src/utils.rs b/juniper_graphql_ws/src/utils.rs new file mode 100644 index 000000000..75106a4cf --- /dev/null +++ b/juniper_graphql_ws/src/utils.rs @@ -0,0 +1,9 @@ +use serde::{Deserialize, Deserializer}; + +pub(crate) fn default_for_null<'de, D, T>(deserializer: D) -> Result +where + D: Deserializer<'de>, + T: Deserialize<'de> + Default, +{ + Ok(Option::::deserialize(deserializer)?.unwrap_or_default()) +}