diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cecafc4..eb28ab87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ nd this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0. - Add cache support for DataLoader. [#455](https://github.com/async-graphql/async-graphql/issues/455) - Prevent Warp WS Close, Ping, and Pong messages from being parsed as GraphQL [#459](https://github.com/async-graphql/async-graphql/pull/459) +- Implements `ScalarType` for `serde_json::Value`. ## [2.7.2] diff --git a/src/dataloader/mod.rs b/src/dataloader/mod.rs index 349d7bf6..c137ad24 100644 --- a/src/dataloader/mod.rs +++ b/src/dataloader/mod.rs @@ -85,6 +85,8 @@ struct Requests> { cache_storage: Box>, } +type KeysAndSender = (HashSet, Vec<(HashSet, ResSender)>); + impl> Requests { fn new(cache_factory: &C) -> Self { Self { @@ -94,7 +96,7 @@ impl> Requests } } - fn take(&mut self) -> (HashSet, Vec<(HashSet, ResSender)>) { + fn take(&mut self) -> KeysAndSender { ( std::mem::take(&mut self.keys), std::mem::take(&mut self.pending), diff --git a/src/extensions/opentelemetry.rs b/src/extensions/opentelemetry.rs index 8392e4bd..b16c111d 100644 --- a/src/extensions/opentelemetry.rs +++ b/src/extensions/opentelemetry.rs @@ -119,9 +119,10 @@ impl Extension for OpenTelemetryExtension { variables: &Variables, ) { if let Some(parent_cx) = self.contexts.get(&REQUEST_CTX).cloned() { - let mut attributes = Vec::with_capacity(2); - attributes.push(KEY_SOURCE.string(query_source.to_string())); - attributes.push(KEY_VARIABLES.string(serde_json::to_string(variables).unwrap())); + let attributes = vec![ + KEY_SOURCE.string(query_source.to_string()), + KEY_VARIABLES.string(serde_json::to_string(variables).unwrap()), + ]; let parse_span = self .tracer .span_builder("parse") @@ -189,10 +190,11 @@ impl Extension for OpenTelemetryExtension { .cloned(); if let Some(parent_cx) = parent_cx { - let mut attributes = Vec::with_capacity(3); - attributes.push(KEY_RESOLVE_ID.i64(info.resolve_id.current as i64)); - attributes.push(KEY_PARENT_TYPE.string(info.parent_type.to_string())); - attributes.push(KEY_RETURN_TYPE.string(info.return_type.to_string())); + let attributes = vec![ + KEY_RESOLVE_ID.i64(info.resolve_id.current as i64), + KEY_PARENT_TYPE.string(info.parent_type.to_string()), + KEY_RETURN_TYPE.string(info.return_type.to_string()), + ]; let span = self .tracer .span_builder(&info.path_node.to_string()) diff --git a/src/types/json.rs b/src/types/json.rs index c49fa7fb..065397f9 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -7,8 +7,8 @@ use serde::{Deserialize, Serialize}; use crate::parser::types::Field; use crate::registry::{MetaType, Registry}; use crate::{ - from_value, to_value, ContextSelectionSet, InputValueResult, OutputType, Positioned, Scalar, - ScalarType, ServerResult, Type, Value, + from_value, to_value, ContextSelectionSet, InputValueError, InputValueResult, OutputType, + Positioned, Scalar, ScalarType, ServerResult, Type, Value, }; /// A scalar that can represent any JSON value. @@ -100,6 +100,20 @@ impl OutputType for OutputJson { } } +/// A scalar that can represent any JSON value. +#[Scalar(internal, name = "JSON")] +impl ScalarType for serde_json::Value { + fn parse(value: Value) -> InputValueResult { + value + .into_json() + .map_err(|_| InputValueError::custom("Invalid JSON")) + } + + fn to_value(&self) -> Value { + Value::from_json(self.clone()).unwrap_or_default() + } +} + #[cfg(test)] mod test { use crate::*;