InputObject

You can use an Object as an argument, and GraphQL calls it an InputObject.

The definition of InputObject is similar to SimpleObject, but SimpleObject can only be used as output and InputObject can only be used as input.

You can add optional #[graphql] attributes to add descriptions or rename the field.

#![allow(unused)]
fn main() {
extern crate async_graphql;
#[derive(SimpleObject)]
struct User { a: i32 }
use async_graphql::*;

#[derive(InputObject)]
struct Coordinate {
    latitude: f64,
    longitude: f64
}

struct Mutation;

#[Object]
impl Mutation {
    async fn users_at_location(&self, coordinate: Coordinate, radius: f64) -> Vec<User> {
        // Writes coordination to database.
        // ...
      todo!()
    }
}
}

Generic InputObjects

If you want to reuse an InputObject for other types, you can define a generic InputObject and specify how its concrete types should be implemented.

In the following example, two InputObject types are created:

#![allow(unused)]
fn main() {
extern crate async_graphql;
use async_graphql::*;
#[derive(InputObject)]
struct SomeType { a: i32 }
#[derive(InputObject)]
struct SomeOtherType { a: i32 }
#[derive(InputObject)]
#[graphql(concrete(name = "SomeName", params(SomeType)))]
#[graphql(concrete(name = "SomeOtherName", params(SomeOtherType)))]
pub struct SomeGenericInput<T: InputType> {
    field1: Option<T>,
    field2: String
}
}

Note: Each generic parameter must implement InputType, as shown above.

The schema generated is:

input SomeName {
  field1: SomeType
  field2: String!
}

input SomeOtherName {
  field1: SomeOtherType
  field2: String!
}

In your resolver method or field of another input object, use as a normal generic type:

#![allow(unused)]
fn main() {
extern crate async_graphql;
use async_graphql::*;
#[derive(InputObject)]
struct SomeType { a: i32 }
#[derive(InputObject)]
struct SomeOtherType { a: i32 }
#[derive(InputObject)]
#[graphql(concrete(name = "SomeName", params(SomeType)))]
#[graphql(concrete(name = "SomeOtherName", params(SomeOtherType)))]
pub struct SomeGenericInput<T: InputType> {
    field1: Option<T>,
    field2: String
}
#[derive(InputObject)]
pub struct YetAnotherInput {
    a: SomeGenericInput<SomeType>,
    b: SomeGenericInput<SomeOtherType>,
}
}

You can pass multiple generic types to params(), separated by a comma.

Redacting sensitive data

If any part of your input is considered sensitive and you wish to redact it, you can mark it with secret directive. For example:

#![allow(unused)]
fn main() {
extern crate async_graphql;
use async_graphql::*;
#[derive(InputObject)]
pub struct CredentialsInput {
    username: String,
    #[graphql(secret)]
    password: String,
}
}

Flattening fields

You can add #[graphql(flatten)] to a field to inline keys from the field type into it's parent. For example:

#![allow(unused)]
fn main() {
extern crate async_graphql;
use async_graphql::*;
#[derive(InputObject)]
pub struct ChildInput {
    b: String,
    c: String,
}

#[derive(InputObject)]
pub struct ParentInput {
    a: String,
    #[graphql(flatten)]
    child: ChildInput,
}

// Is the same as

#[derive(InputObject)]
pub struct Input {
    a: String,
    b: String,
    c: String,
}
}