2022-04-19 04:25:11 +00:00
|
|
|
use std::{
|
|
|
|
borrow::Cow,
|
|
|
|
ops::{Deref, DerefMut},
|
|
|
|
};
|
2020-10-15 06:38:10 +00:00
|
|
|
|
2022-04-19 04:25:11 +00:00
|
|
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
2020-10-15 06:38:10 +00:00
|
|
|
|
2020-07-08 06:44:57 +00:00
|
|
|
use crate::{
|
2022-04-19 04:25:11 +00:00
|
|
|
from_value,
|
|
|
|
parser::types::Field,
|
|
|
|
registry::{MetaType, MetaTypeId, Registry},
|
|
|
|
to_value, ContextSelectionSet, InputType, InputValueResult, OutputType, Positioned,
|
2021-11-18 07:43:12 +00:00
|
|
|
ServerResult, Value,
|
2020-07-08 06:44:57 +00:00
|
|
|
};
|
2020-05-07 12:41:00 +00:00
|
|
|
|
|
|
|
/// A scalar that can represent any JSON value.
|
2020-09-08 08:21:27 +00:00
|
|
|
///
|
2022-04-19 04:25:11 +00:00
|
|
|
/// If the inner type cannot be serialized as JSON (e.g. it has non-string keys)
|
|
|
|
/// it will be `null`.
|
2020-06-02 13:00:54 +00:00
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Hash, Default)]
|
2020-09-08 08:21:27 +00:00
|
|
|
#[serde(transparent)]
|
2020-05-07 12:41:00 +00:00
|
|
|
pub struct Json<T>(pub T);
|
|
|
|
|
|
|
|
impl<T> Deref for Json<T> {
|
|
|
|
type Target = T;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> DerefMut for Json<T> {
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
&mut self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-18 07:43:12 +00:00
|
|
|
impl<T> From<T> for Json<T> {
|
2020-09-08 08:21:27 +00:00
|
|
|
fn from(value: T) -> Self {
|
2020-07-08 06:44:57 +00:00
|
|
|
Self(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-18 07:43:12 +00:00
|
|
|
impl<T: DeserializeOwned + Serialize + Send + Sync> InputType for Json<T> {
|
|
|
|
type RawValueType = T;
|
2020-05-07 12:41:00 +00:00
|
|
|
|
2021-11-18 07:43:12 +00:00
|
|
|
fn type_name() -> Cow<'static, str> {
|
|
|
|
Cow::Borrowed("JSON")
|
2020-05-07 12:41:00 +00:00
|
|
|
}
|
|
|
|
|
2021-11-18 07:43:12 +00:00
|
|
|
fn create_type_info(registry: &mut Registry) -> String {
|
2022-03-30 12:54:49 +00:00
|
|
|
registry.create_input_type::<Json<T>, _>(MetaTypeId::Scalar, |_| MetaType::Scalar {
|
2021-11-18 07:43:12 +00:00
|
|
|
name: <Self as InputType>::type_name().to_string(),
|
2021-12-07 03:28:43 +00:00
|
|
|
description: Some("A scalar that can represent any JSON value."),
|
2021-11-18 07:43:12 +00:00
|
|
|
is_valid: |_| true,
|
|
|
|
visible: None,
|
2022-08-18 09:40:04 +00:00
|
|
|
inaccessible: false,
|
2022-08-22 09:44:02 +00:00
|
|
|
tags: Default::default(),
|
2021-11-18 07:43:12 +00:00
|
|
|
specified_by_url: None,
|
|
|
|
})
|
|
|
|
}
|
2020-07-08 06:44:57 +00:00
|
|
|
|
2021-11-18 07:43:12 +00:00
|
|
|
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
|
|
|
Ok(from_value(value.unwrap_or_default())?)
|
2020-07-08 06:44:57 +00:00
|
|
|
}
|
|
|
|
|
2021-11-18 07:43:12 +00:00
|
|
|
fn to_value(&self) -> Value {
|
2022-07-04 22:55:01 +00:00
|
|
|
Value::String(serde_json::to_string(&self.0).unwrap_or_default())
|
2020-07-08 06:44:57 +00:00
|
|
|
}
|
|
|
|
|
2021-11-18 07:43:12 +00:00
|
|
|
fn as_raw_value(&self) -> Option<&Self::RawValueType> {
|
|
|
|
Some(&self.0)
|
2020-05-11 15:55:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-09 10:52:10 +00:00
|
|
|
#[async_trait::async_trait]
|
2021-11-18 07:43:12 +00:00
|
|
|
impl<T: Serialize + Send + Sync> OutputType for Json<T> {
|
2020-07-08 06:44:57 +00:00
|
|
|
fn type_name() -> Cow<'static, str> {
|
2021-11-18 07:43:12 +00:00
|
|
|
Cow::Borrowed("JSON")
|
2020-07-08 06:44:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn create_type_info(registry: &mut Registry) -> String {
|
2022-03-30 12:54:49 +00:00
|
|
|
registry.create_output_type::<Json<T>, _>(MetaTypeId::Scalar, |_| MetaType::Scalar {
|
2021-11-18 07:43:12 +00:00
|
|
|
name: <Self as OutputType>::type_name().to_string(),
|
2021-12-07 03:28:43 +00:00
|
|
|
description: Some("A scalar that can represent any JSON value."),
|
2020-07-08 06:44:57 +00:00
|
|
|
is_valid: |_| true,
|
2020-12-11 08:03:28 +00:00
|
|
|
visible: None,
|
2022-08-18 09:40:04 +00:00
|
|
|
inaccessible: false,
|
2022-08-22 09:44:02 +00:00
|
|
|
tags: Default::default(),
|
2021-10-28 07:21:42 +00:00
|
|
|
specified_by_url: None,
|
2020-07-08 06:44:57 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-06-07 12:51:20 +00:00
|
|
|
async fn resolve(
|
|
|
|
&self,
|
|
|
|
_ctx: &ContextSelectionSet<'_>,
|
|
|
|
_field: &Positioned<Field>,
|
|
|
|
) -> ServerResult<Value> {
|
|
|
|
Ok(to_value(&self.0).ok().unwrap_or_default())
|
2020-07-08 06:44:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-29 14:14:27 +00:00
|
|
|
impl InputType for serde_json::Value {
|
|
|
|
type RawValueType = serde_json::Value;
|
|
|
|
|
|
|
|
fn type_name() -> Cow<'static, str> {
|
|
|
|
Cow::Borrowed("JSON")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_type_info(registry: &mut Registry) -> String {
|
2022-03-30 12:54:49 +00:00
|
|
|
registry.create_input_type::<serde_json::Value, _>(MetaTypeId::Scalar, |_| {
|
|
|
|
MetaType::Scalar {
|
|
|
|
name: <Self as InputType>::type_name().to_string(),
|
|
|
|
description: Some("A scalar that can represent any JSON value."),
|
|
|
|
is_valid: |_| true,
|
|
|
|
visible: None,
|
2022-08-18 09:40:04 +00:00
|
|
|
inaccessible: false,
|
2022-08-22 09:44:02 +00:00
|
|
|
tags: Default::default(),
|
2022-03-30 12:54:49 +00:00
|
|
|
specified_by_url: None,
|
|
|
|
}
|
2021-11-29 14:14:27 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse(value: Option<Value>) -> InputValueResult<Self> {
|
|
|
|
Ok(from_value(value.unwrap_or_default())?)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn to_value(&self) -> Value {
|
2022-07-04 22:55:01 +00:00
|
|
|
Value::String(self.to_string())
|
2021-11-29 14:14:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn as_raw_value(&self) -> Option<&Self::RawValueType> {
|
|
|
|
Some(&self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait]
|
|
|
|
impl OutputType for serde_json::Value {
|
|
|
|
fn type_name() -> Cow<'static, str> {
|
|
|
|
Cow::Borrowed("JSON")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_type_info(registry: &mut Registry) -> String {
|
2022-03-30 12:54:49 +00:00
|
|
|
registry.create_output_type::<serde_json::Value, _>(MetaTypeId::Scalar, |_| {
|
|
|
|
MetaType::Scalar {
|
|
|
|
name: <Self as OutputType>::type_name().to_string(),
|
|
|
|
description: Some("A scalar that can represent any JSON value."),
|
|
|
|
is_valid: |_| true,
|
|
|
|
visible: None,
|
2022-08-18 09:40:04 +00:00
|
|
|
inaccessible: false,
|
2022-08-22 09:44:02 +00:00
|
|
|
tags: Default::default(),
|
2022-03-30 12:54:49 +00:00
|
|
|
specified_by_url: None,
|
|
|
|
}
|
2021-11-29 14:14:27 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn resolve(
|
|
|
|
&self,
|
|
|
|
_ctx: &ContextSelectionSet<'_>,
|
|
|
|
_field: &Positioned<Field>,
|
|
|
|
) -> ServerResult<Value> {
|
|
|
|
Ok(to_value(&self).ok().unwrap_or_default())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-07 12:41:00 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
2022-04-19 04:25:11 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
use crate::*;
|
|
|
|
|
2021-03-12 04:47:24 +00:00
|
|
|
#[tokio::test]
|
2020-05-07 12:41:00 +00:00
|
|
|
async fn test_json_type() {
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
struct MyStruct {
|
|
|
|
a: i32,
|
|
|
|
b: i32,
|
|
|
|
c: HashMap<String, i32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Query;
|
|
|
|
|
2020-09-18 00:52:13 +00:00
|
|
|
#[Object(internal)]
|
2020-05-07 12:41:00 +00:00
|
|
|
impl Query {
|
|
|
|
async fn obj(&self, input: Json<MyStruct>) -> Json<MyStruct> {
|
|
|
|
input
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let query = r#"{ obj(input: { a: 1, b: 2, c: { a: 11, b: 22 } } ) }"#;
|
|
|
|
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
|
|
|
assert_eq!(
|
2020-09-10 23:58:02 +00:00
|
|
|
schema.execute(query).await.into_result().unwrap().data,
|
2020-10-12 02:17:05 +00:00
|
|
|
value!({
|
2020-05-07 12:41:00 +00:00
|
|
|
"obj": {
|
|
|
|
"a": 1,
|
|
|
|
"b": 2,
|
|
|
|
"c": { "a": 11, "b": 22 }
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
2020-09-14 08:17:53 +00:00
|
|
|
|
2021-03-12 04:47:24 +00:00
|
|
|
#[tokio::test]
|
2021-11-18 07:43:12 +00:00
|
|
|
async fn test_json_type_for_serialize_only() {
|
2020-09-14 08:17:53 +00:00
|
|
|
#[derive(Serialize)]
|
|
|
|
struct MyStruct {
|
|
|
|
a: i32,
|
|
|
|
b: i32,
|
|
|
|
c: HashMap<String, i32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Query;
|
|
|
|
|
2020-09-18 00:52:13 +00:00
|
|
|
#[Object(internal)]
|
2020-09-14 08:17:53 +00:00
|
|
|
impl Query {
|
2021-11-18 07:43:12 +00:00
|
|
|
async fn obj(&self) -> Json<MyStruct> {
|
2020-09-14 08:17:53 +00:00
|
|
|
MyStruct {
|
|
|
|
a: 1,
|
|
|
|
b: 2,
|
|
|
|
c: {
|
|
|
|
let mut values = HashMap::new();
|
|
|
|
values.insert("a".to_string(), 11);
|
|
|
|
values.insert("b".to_string(), 22);
|
|
|
|
values
|
|
|
|
},
|
|
|
|
}
|
|
|
|
.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let query = r#"{ obj }"#;
|
|
|
|
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
|
|
|
assert_eq!(
|
|
|
|
schema.execute(query).await.into_result().unwrap().data,
|
2020-10-12 02:17:05 +00:00
|
|
|
value!({
|
2020-09-14 08:17:53 +00:00
|
|
|
"obj": {
|
|
|
|
"a": 1,
|
|
|
|
"b": 2,
|
|
|
|
"c": { "a": 11, "b": 22 }
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
2020-05-07 12:41:00 +00:00
|
|
|
}
|