diff --git a/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt b/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt index b280c463..469a24a4 100644 --- a/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt +++ b/src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt @@ -266,13 +266,16 @@ internal class LightMethodFieldResolverDataFetcher( private fun Any.transformWithGenericWrapper( genericWrappers: List, environmentSupplier: Supplier -): Any { - return genericWrappers +): Any? { + val genericWrapper = genericWrappers .asSequence() .filter { it.type.isInstance(this) } .sortedWith(CompareGenericWrappers) .firstOrNull() - ?.transformer?.invoke(this, environmentSupplier.get()) ?: this + ?: return this + + // returned as is, even if null, so a transformer can map a value to null + return genericWrapper.transformer(this, environmentSupplier.get()) } private class CompareGenericWrappers { diff --git a/src/test/kotlin/graphql/kickstart/tools/MethodFieldResolverTest.kt b/src/test/kotlin/graphql/kickstart/tools/MethodFieldResolverTest.kt index b64c5ac2..a59503df 100644 --- a/src/test/kotlin/graphql/kickstart/tools/MethodFieldResolverTest.kt +++ b/src/test/kotlin/graphql/kickstart/tools/MethodFieldResolverTest.kt @@ -239,6 +239,51 @@ class MethodFieldResolverTest { assertEquals(exceptionWhileDataFetching.exception.message, "Whoops") } + @Test + fun `should return null when generic wrapper transformer returns null`() { + val schema = SchemaParser.newParser() + .schemaString( + """ + type Query { + name: String + names: [String!] + nameWithArgument(input: String): String + } + """) + .resolvers(object : GraphQLQueryResolver { + fun name(): Maybe = Maybe.None + fun names(): Maybe> = Maybe.None + fun nameWithArgument(input: String?): Maybe = Maybe.None + }) + .options(SchemaParserOptions.newOptions() + .genericWrappers(SchemaParserOptions.GenericWrapper.withTransformer(Maybe::class, 0, { maybe -> (maybe as? Maybe.Some)?.value })) + .build()) + .build() + .makeExecutableSchema() + + val gql = GraphQL.newGraphQL(schema).build() + val result = gql.execute(ExecutionInput.newExecutionInput().query( + """ + query { + name + names + nameWithArgument(input: "test") + } + """)) + + assertEquals(result.errors, listOf()) + assertEquals(result.getData(), mapOf( + "name" to null, + "names" to null, + "nameWithArgument" to null + )) + } + + sealed class Maybe { + data class Some(val value: T) : Maybe() + object None : Maybe() + } + /** * Custom Scalar Class type that doesn't work with Jackson serialization/deserialization */