Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix serializing of JSON default values #969

Merged
merged 2 commits into from Jul 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 5 additions & 7 deletions integrations/actix-web/tests/graphql.rs
Expand Up @@ -137,13 +137,11 @@ async fn test_hello_header() {
async fn test_count() {
let srv = test::init_service(
App::new()
.app_data(
Data::new(
Schema::build(CountQueryRoot, CountMutation, EmptySubscription)
.data(Count::default())
.finish(),
),
)
.app_data(Data::new(
Schema::build(CountQueryRoot, CountMutation, EmptySubscription)
.data(Count::default())
.finish(),
))
.service(
web::resource("/")
.guard(guard::Post())
Expand Down
7 changes: 3 additions & 4 deletions src/extensions/opentelemetry.rs
Expand Up @@ -83,14 +83,13 @@ where
next: NextSubscribe<'_>,
) -> BoxStream<'s, Response> {
Box::pin(
next.run(ctx, stream).with_context(
OpenTelemetryContext::current_with_span(
next.run(ctx, stream)
.with_context(OpenTelemetryContext::current_with_span(
self.tracer
.span_builder("subscribe")
.with_kind(SpanKind::Server)
.start(&*self.tracer),
),
),
)),
)
}

Expand Down
4 changes: 2 additions & 2 deletions src/types/json.rs
Expand Up @@ -63,7 +63,7 @@ impl<T: DeserializeOwned + Serialize + Send + Sync> InputType for Json<T> {
}

fn to_value(&self) -> Value {
to_value(&self.0).unwrap_or_default()
Value::String(serde_json::to_string(&self.0).unwrap_or_default())
}

fn as_raw_value(&self) -> Option<&Self::RawValueType> {
Expand Down Expand Up @@ -120,7 +120,7 @@ impl InputType for serde_json::Value {
}

fn to_value(&self) -> Value {
to_value(&self).unwrap_or_default()
Value::String(self.to_string())
}

fn as_raw_value(&self) -> Option<&Self::RawValueType> {
Expand Down
133 changes: 133 additions & 0 deletions tests/introspection.rs
@@ -1,4 +1,5 @@
use async_graphql::*;
use chrono::{NaiveDate, NaiveDateTime};
use futures_util::stream::{self, Stream};

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -1378,3 +1379,135 @@ pub async fn test_introspection_only() {
let res = schema.execute(query).await.into_result().unwrap().data;
assert_eq!(res, res_json);
}

#[tokio::test]
pub async fn test_introspection_default() {
#[derive(serde::Serialize, serde::Deserialize, Default)]
pub struct MyStruct {
a: i32,
b: i32,
}

#[derive(InputObject)]
pub struct DefaultInput {
#[graphql(default)]
pub str: String,
#[graphql(default_with = "NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11)")]
pub date: NaiveDateTime,
// a required json with no default
pub json: serde_json::Value,
// basic default (JSON null)
#[graphql(default)]
pub json_def: serde_json::Value,
// complex default (JSON object)
#[graphql(default_with = "serde_json::Value::Object(Default::default())")]
pub json_def_obj: serde_json::Value,
#[graphql(default)]
pub json_def_struct: Json<MyStruct>,
}

struct LocalMutation;

#[Object]
#[allow(unreachable_code)]
impl LocalMutation {
async fn simple_mutation(&self, _input: DefaultInput) -> SimpleObject {
unimplemented!()
}
}

let schema = Schema::build(Query, LocalMutation, EmptySubscription)
.introspection_only()
.finish();

// Test whether introspection works.
let query = r#"
{
__type(name: "DefaultInput") {
name
kind
inputFields {
name
defaultValue
type { kind ofType { kind name } }
}
}
}
"#;
let res_json = value!({
"__type": {
"name": "DefaultInput",
"kind": "INPUT_OBJECT",
"inputFields": [
{
"name": "str",
"defaultValue": "\"\"",
"type": {
"kind": "NON_NULL",
"ofType": {
"kind": "SCALAR",
"name": "String"
},
},
},
{
"name": "date",
"defaultValue": "\"2016-07-08T09:10:11\"",
"type": {
"kind": "NON_NULL",
"ofType": {
"kind": "SCALAR",
"name": "NaiveDateTime"
},
},
},
{
"name": "json",
"defaultValue": null,
"type": {
"kind": "NON_NULL",
"ofType": {
"kind": "SCALAR",
"name": "JSON"
},
},
},
{
"name": "jsonDef",
"defaultValue": "\"null\"",
"type": {
"kind": "NON_NULL",
"ofType": {
"kind": "SCALAR",
"name": "JSON"
},
},
},
{
"name": "jsonDefObj",
"defaultValue": "\"{}\"",
"type": {
"kind": "NON_NULL",
"ofType": {
"kind": "SCALAR",
"name": "JSON"
},
},
},
{
"name": "jsonDefStruct",
"defaultValue": "\"{\\\"a\\\":0,\\\"b\\\":0}\"",
"type": {
"kind": "NON_NULL",
"ofType": {
"kind": "SCALAR",
"name": "JSON"
},
},
},
]
}
});
let res = schema.execute(query).await.into_result().unwrap().data;
assert_eq!(res, res_json);
}