@@ -14,8 +14,6 @@ import graphql.schema.DataFetchingEnvironment
1414import graphql.schema.GraphQLTypeUtil.isScalar
1515import kotlinx.coroutines.future.future
1616import java.lang.reflect.Method
17- import java.lang.reflect.ParameterizedType
18- import java.lang.reflect.WildcardType
1917import java.util.*
2018import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
2119import kotlin.reflect.full.valueParameters
@@ -82,15 +80,13 @@ internal class MethodFieldResolver(
8280 return @add Optional .empty<Any >()
8381 }
8482
85- if (value != null
86- && parameterType.unwrap().isAssignableFrom( value.javaClass)
87- && isScalarType(environment, definition.type, parameterType)) {
88- return @add value
83+ if (value != null && shouldValueBeConverted(value, definition, parameterType, environment)) {
84+ return @add mapper.convertValue( value, object : TypeReference < Any >() {
85+ override fun getType () = parameterType
86+ })
8987 }
9088
91- return @add mapper.convertValue(value, object : TypeReference <Any >() {
92- override fun getType () = parameterType
93- })
89+ return @add value
9490 }
9591 }
9692
@@ -110,22 +106,25 @@ internal class MethodFieldResolver(
110106 }
111107 }
112108
113- private fun isScalarType (environment : DataFetchingEnvironment , type : Type <* >, genericParameterType : JavaType ): Boolean =
114- when (type) {
109+ private fun shouldValueBeConverted (value : Any , definition : InputValueDefinition , parameterType : JavaType , environment : DataFetchingEnvironment ): Boolean {
110+ return ! parameterType.unwrap().isAssignableFrom(value.javaClass) || ! isConcreteScalarType(environment, definition.type, parameterType)
111+ }
112+
113+ /* *
114+ * A concrete scalar type is a scalar type where values always coerce to the same Java type. The ID scalar type is not concrete
115+ * because values can be coerced to multiple different Java types (eg. String, Long, UUID). All values of a non-concrete scalar
116+ * type must be converted to the target method parameter type.
117+ */
118+ private fun isConcreteScalarType (environment : DataFetchingEnvironment , type : Type <* >, genericParameterType : JavaType ): Boolean {
119+ return when (type) {
115120 is ListType -> List ::class .java.isAssignableFrom(this .genericType.getRawClass(genericParameterType))
116- && isScalarType (environment, type.type, this .genericType.unwrapGenericType(genericParameterType))
117- is TypeName -> environment.graphQLSchema?.getType(type.name)?.let { isScalar(it) && ! isJavaLanguageType(genericParameterType) }
121+ && isConcreteScalarType (environment, type.type, this .genericType.unwrapGenericType(genericParameterType))
122+ is TypeName -> environment.graphQLSchema?.getType(type.name)?.let { isScalar(it) && type.name != " ID " }
118123 ? : false
119- is NonNullType -> isScalarType (environment, type.type, genericParameterType)
124+ is NonNullType -> isConcreteScalarType (environment, type.type, genericParameterType)
120125 else -> false
121126 }
122-
123- private fun isJavaLanguageType (type : JavaType ): Boolean =
124- when (type) {
125- is ParameterizedType -> isJavaLanguageType(type.actualTypeArguments[0 ])
126- is WildcardType -> isJavaLanguageType(type.upperBounds[0 ])
127- else -> genericType.getRawClass(type).`package`.name == " java.lang"
128- }
127+ }
129128
130129 override fun scanForMatches (): List <TypeClassMatcher .PotentialMatch > {
131130 val unwrappedGenericType = genericType.unwrapGenericType(try {
0 commit comments