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
andnone
(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.