@@ -14,8 +14,6 @@ import graphql.schema.DataFetchingEnvironment
14
14
import graphql.schema.GraphQLTypeUtil.isScalar
15
15
import kotlinx.coroutines.future.future
16
16
import java.lang.reflect.Method
17
- import java.lang.reflect.ParameterizedType
18
- import java.lang.reflect.WildcardType
19
17
import java.util.*
20
18
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
21
19
import kotlin.reflect.full.valueParameters
@@ -82,15 +80,13 @@ internal class MethodFieldResolver(
82
80
return @add Optional .empty<Any >()
83
81
}
84
82
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
+ })
89
87
}
90
88
91
- return @add mapper.convertValue(value, object : TypeReference <Any >() {
92
- override fun getType () = parameterType
93
- })
89
+ return @add value
94
90
}
95
91
}
96
92
@@ -110,22 +106,25 @@ internal class MethodFieldResolver(
110
106
}
111
107
}
112
108
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) {
115
120
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 " }
118
123
? : false
119
- is NonNullType -> isScalarType (environment, type.type, genericParameterType)
124
+ is NonNullType -> isConcreteScalarType (environment, type.type, genericParameterType)
120
125
else -> false
121
126
}
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
+ }
129
128
130
129
override fun scanForMatches (): List <TypeClassMatcher .PotentialMatch > {
131
130
val unwrappedGenericType = genericType.unwrapGenericType(try {
0 commit comments