Optional Undefined Arguments
In the GraphQL world, input types can be optional which means that the client can either:
- Not specify a value at all
- Send null explicitly
- Send a non-null value
This is in contrast with the JVM world where objects can either have some specific value or don't have any value (i.e.
are null
). As a result, when using default serialization logic it is not possible to distinguish between missing/unspecified
value and explicit null
value.
Using OptionalInput wrapper
OptionalInput
is a convenient sealed class wrapper that provides distinction between undefined, null, and non-null
values. If the argument is not specified in the request it will be represented as a OptionalInput.Undefined
object, otherwise the
value will be wrapped in OptionalInput.Defined
class.
fun optionalInput(input: OptionalInput<String>): String = when (input) {
is OptionalInput.Undefined -> "input was not specified"
is OptionalInput.Defined<String> -> "input value: ${input.value}"
}
query OptionalInputQuery {
undefined: optionalInput # input was not specified
null: optionalInput(value: null) # input value: null
foo: optionalInput(value: "foo") # input value: foo
}
Regardless whether the generic type of OptionalInput
is specified as nullable or not it will always result in a nullable
value in Defined
class, i.e. OptionalInput<String>
will appear as nullable String
in the GraphQL schema and in the wrapped value.
Using DataFetchingEnvironment
Optional input types can be represented as nullable parameters in Kotlin
fun optionalInput(value: String?): String? = value
query OptionalInputQuery {
undefined: optionalInput # null
null: optionalInput(value: null) # null
foo: optionalInput(value: "foo") # foo
}
By default, if an optional input value is not specified, then the execution engine will set the argument in Kotlin to null
.
This means that you can not tell, by just the value alone, whether the request did not contain any argument or the client
explicitly passed in null
.
Instead, you can inspect all passed in arguments using the DataFetchingEnvironment.
fun optionalInput(value: String?, dataFetchingEnvironment: DataFetchingEnvironment): String =
if (dataFetchingEnvironment.containsArgument("value")) {
"The value was $value"
} else {
"The value was undefined"
}
Kotlin Default Values
If you don't need logic for when the client specified a value, you can still use Kotlin default values