Input Objects
A GraphQL Input Object defines a set of input fields; the input fields are either scalars, enums, or other input objects. Like Object and Interface types, Input Object types are inferred from defined operations, but can be explicitly declared as well.
Schema
Input Objects take their fields from the primary constructor, supporting property and non-property parameters.
// Non-data class with a constructor parameter that is not a property
class NonDataClass(param1: String = "Hello", val param3: Boolean?) {
var param2: Int = param1.length
}
val schema = KGraphQL.schema {
query("test") {
resolver { input: NonDataClass -> input }
}
}
type NonDataClass {
param2: Int!
param3: Boolean
}
type Query {
test(input: NonDataClassInput!): NonDataClass!
}
input NonDataClassInput {
param1: String!
param3: Boolean
}
Input Type Name
To avoid equal names between input and query types, input types get an automated "Input" suffix unless their name
already ends with "Input" or they have explicit configuration in the DSL via inputType {}.
In this case, the input type Type will automatically be renamed to TypeInput but FooInput will not become
FooInputInput:
class Type(val name: String)
data class FooInput(val name: String)
data class Foo(val name: String)
val schema = KGraphQL.schema {
query("getFoo") {
resolver { -> Foo("bar") }
}
mutation("addType") {
resolver { input: Type -> input }
}
mutation("addFoo") {
resolver { input: FooInput -> Foo(input.name) }
}
}
type Foo {
name: String!
}
type Mutation {
addFoo(input: FooInput!): Foo!
addType(input: TypeInput!): Type!
}
type Query {
getFoo: Foo!
}
type Type {
name: String!
}
input FooInput {
name: String!
}
input TypeInput {
name: String!
}
This behavior applies recursively to nested types as well. The nested ChildType will also be renamed to ChildTypeInput:
class ChildType(val childName: String)
class ParentType(val parentName: String, val child: ChildType)
val schema = KGraphQL.schema {
query("getParent") {
resolver { -> ParentType("parent", ChildType("child")) }
}
mutation("addParent") {
resolver { input: ParentType -> input }
}
}
type ChildType {
childName: String!
}
type Mutation {
addParent(input: ParentTypeInput!): ParentType!
}
type ParentType {
child: ChildType!
parentName: String!
}
type Query {
getParent: ParentType!
}
input ChildTypeInput {
childName: String!
}
input ParentTypeInput {
child: ChildTypeInput!
parentName: String!
}
Configuration
Input types can be configured via the inputType DSL.
inputType<InputObject> {
name = "MyInputObject"
description = "Description for input object"
InputObject::foo.configure {
deprecate("Deprecated old input value")
}
}
Whenever an input type is configured via DSL the automatic suffix will not be appended, regardless of the name.
Here, both InputType and ParentType are explicitly configured, and therefore will keep their original name (a custom
name is not required).
class InputType(val name: String)
class Type(val name: String)
class ChildType(val childName: String)
class ParentType(val parentName: String, val child: ChildType)
val schema = KGraphQL.schema {
query("getType") {
resolver { -> Type("type") }
}
mutation("addType") {
resolver { input: InputType -> Type(input.name) }
}
mutation("addParent") {
resolver { input: ParentType -> input }
}
inputType<InputType>()
inputType<ParentType> {
name = "MyParentInputType"
}
}
type ChildType {
childName: String!
}
type Mutation {
addParent(input: MyParentInputType!): ParentType!
addType(input: InputType!): Type!
}
type ParentType {
child: ChildType!
parentName: String!
}
type Query {
getType: Type!
}
type Type {
name: String!
}
input ChildTypeInput {
childName: String!
}
input InputType {
name: String!
}
input MyParentInputType {
child: ChildTypeInput!
parentName: String!
}
OneOf Input Objects
Input Objects configured with isOneOf = true in the inputType DSL (or declared with the @oneOf directive in SDL)
result in a OneOf Input Object.
OneOf Input Objects are a special variant of an Input Object where exactly one field must be set and non-null, all others being omitted. This is useful for representing situations where an input may be one of many different options.
Simplified Entrypoints
For example, you might find a user by their ID, email address, or username. Traditionally, that meant multiple root-level fields:
type Query {
user(id: ID!): User
userByEmail(email: String!): User
userByUsername(username: String!): User
}
With oneOf this can now be represented in a more concise and user-friendly way:
input UserBy @oneOf {
id: ID
email: String
username: String
}
type Query {
user(by: UserBy!): User
}
Polymorph Inputs
Imagine a blogging website with posts that consist of different types of content, such as paragraphs, images, and quotes. OneOf Input Objects allow you to define a mutation that accepts a type-safe list of such elements:
type Mutation {
createPost(elements: [PostElementInput]): Post
}
input PostElementInput @oneOf {
paragraph: ParagraphInput
blockquote: BlockQuoteInput
gallery: GalleryInput
}
input ParagraphInput {
text: String!
}
input BlockQuoteInput {
text: String!
attribution: String
attributionUrl: String
}
input GalleryInput {
imageUrls: [String!]!
caption: String
attribution: String
}
Runtime
Input Objects are instantiated via their primary constructor. Kotlin default values are used unless a different value is provided explicitly. Due to a limitation in Kotlin, such default values are not visible in the generated schema, though.
Limitations
Although non-property constructor parameters are supported, it is not possible to add a description or deprecate them.