Input objects

Fields may accept arguments to configure their behavior. These inputs are often scalars or enums, but they sometimes need to represent more complex values.

A GraphQL input object defines a set of input fields; the input fields are either scalars, enums, or other input objects. This allows arguments to accept arbitrarily complex structs.

In Juniper, defining a GraphQL input object is quite straightforward and similar to how trivial GraphQL objects are defined - by using the #[derive(GraphQLInputObject)] attribute on a Rust struct:

#![allow(unused_variables)]
extern crate juniper;
use juniper::{graphql_object, GraphQLInputObject, GraphQLObject};

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

struct Root;
#[derive(GraphQLObject)] struct User { name: String }

#[graphql_object]
impl Root {
    fn users_at_location(coordinate: Coordinate, radius: f64) -> Vec<User> {
        // Send coordinate to database
        // ...
      unimplemented!()
    }
}

fn main() {}

Renaming

Just as with defining GraphQL objects, by default struct fields are converted from Rust's standard snake_case naming convention into GraphQL's camelCase convention:

extern crate juniper;
use juniper::GraphQLInputObject;

#[derive(GraphQLInputObject)]
struct Person {
    first_name: String, // exposed as `firstName` in GraphQL schema
    last_name: String,  // exposed as `lastName` in GraphQL schema
}

fn main() {}

We can override the name by using the #[graphql(name = "...")] attribute:

extern crate juniper;
use juniper::GraphQLInputObject;

#[derive(GraphQLInputObject)]
#[graphql(name = "WebPerson")] // now exposed as `WebPerson` in GraphQL schema
struct Person {
    name: String,
    age: i32,
    #[graphql(name = "websiteURL")]
    website_url: Option<String>, // now exposed as `websiteURL` in GraphQL schema
}

fn main() {}

Or provide a different renaming policy for all the struct fields:

extern crate juniper;
use juniper::GraphQLInputObject;

#[derive(GraphQLInputObject)]
#[graphql(rename_all = "none")] // disables any renaming
struct Person {
    name: String,
    age: i32,
    website_url: Option<String>, // exposed as `website_url` in GraphQL schema
}

fn main() {}

TIP: Supported policies are: SCREAMING_SNAKE_CASE, camelCase and none (disables any renaming).

Documentation

Similarly, GraphQL descriptions may be provided by either using Rust doc comments or with the #[graphql(description = "...")] attribute:

extern crate juniper;
use juniper::GraphQLInputObject;

/// This doc comment is visible only in Rust API docs.
#[derive(GraphQLInputObject)]
#[graphql(description = "This description is visible only in GraphQL schema.")]
struct Person {
    /// This doc comment is visible only in Rust API docs.
    #[graphql(desc = "This description is visible only in GraphQL schema.")]
    //        ^^^^ shortcut for a `description` argument
    name: String,

    /// This doc comment is visible in both Rust API docs and GraphQL schema 
    /// descriptions.
    age: i32,
}

fn main() {}

NOTE: As of October 2021 GraphQL specification, GraphQL input object's fields cannot be deprecated.

Ignoring

By default, all struct fields are included into the generated GraphQL input object type. To prevent inclusion of a specific field annotate it with the #[graphql(ignore)] attribute:

WARNING: Ignored fields must either implement Default or be annotated with the #[graphql(default = <expression>)] argument.

extern crate juniper;
use juniper::GraphQLInputObject;

enum System {
    Cartesian,
}

#[derive(GraphQLInputObject)]
struct Point2D {
    x: f64,
    y: f64,
    #[graphql(ignore, default = System::Cartesian)]
    //                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    // This attribute is required, as we need to be able to construct
    // a `Point2D` value from the `{ x: 0.0, y: 0.0 }` GraphQL input value,
    // received from client-side.
    system: System,
    // `Default::default()` value is used, if no 
    // `#[graphql(default = <expression>)]` is specified.
    #[graphql(skip)]
    //        ^^^^ alternative naming, up to your preference
    shift: f64, 
}

fn main() {}

TIP: See more available features in the API docs of the #[derive(GraphQLInputObject)] attribute.