@@ -11,14 +11,11 @@ import com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer
11
11
import com.fasterxml.jackson.databind.deser.std.StdValueInstantiator
12
12
import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException
13
13
import com.fasterxml.jackson.module.kotlin.ReflectionCache
14
- import com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.ConstructorValueCreator
15
- import com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.MethodValueCreator
16
14
import com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.ValueCreator
15
+ import com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.ValueParameter
17
16
import com.fasterxml.jackson.module.kotlin.isKotlinClass
18
17
import com.fasterxml.jackson.module.kotlin.wrapWithPath
19
- import java.lang.reflect.TypeVariable
20
18
import kotlin.reflect.KParameter
21
- import kotlin.reflect.KType
22
19
import kotlin.reflect.jvm.javaType
23
20
24
21
internal class KotlinValueInstantiator (
@@ -29,6 +26,10 @@ internal class KotlinValueInstantiator(
29
26
private val nullIsSameAsDefault : Boolean ,
30
27
private val strictNullChecks : Boolean
31
28
) : StdValueInstantiator(src) {
29
+ // If the collection type argument cannot be obtained, treat it as nullable
30
+ // @see com.fasterxml.jackson.module.kotlin._ported.test.StrictNullChecksTest#testListOfGenericWithNullValue
31
+ private fun ValueParameter.isNullishTypeAt (index : Int ) = arguments.getOrNull(index)?.isNullable ? : true
32
+
32
33
override fun createFromObjectWith (
33
34
ctxt : DeserializationContext ,
34
35
props : Array <out SettableBeanProperty >,
@@ -37,24 +38,7 @@ internal class KotlinValueInstantiator(
37
38
val valueCreator: ValueCreator <* > = cache.valueCreatorFromJava(_withArgsCreator )
38
39
? : return super .createFromObjectWith(ctxt, props, buffer)
39
40
40
- val propCount: Int
41
- var numCallableParameters: Int
42
- val callableParameters: Array <KParameter ?>
43
- val jsonParamValueList: Array <Any ?>
44
-
45
- if (valueCreator is MethodValueCreator ) {
46
- propCount = props.size + 1
47
- numCallableParameters = 1
48
- callableParameters = arrayOfNulls<KParameter >(propCount)
49
- .apply { this [0 ] = valueCreator.instanceParameter }
50
- jsonParamValueList = arrayOfNulls<Any >(propCount)
51
- .apply { this [0 ] = valueCreator.companionObjectInstance }
52
- } else {
53
- propCount = props.size
54
- numCallableParameters = 0
55
- callableParameters = arrayOfNulls(propCount)
56
- jsonParamValueList = arrayOfNulls(propCount)
57
- }
41
+ val bucket = valueCreator.generateBucket()
58
42
59
43
valueCreator.valueParameters.forEachIndexed { idx, paramDef ->
60
44
val jsonProp = props[idx]
@@ -64,14 +48,14 @@ internal class KotlinValueInstantiator(
64
48
return @forEachIndexed
65
49
}
66
50
67
- var paramVal = if (! isMissing || paramDef.isPrimitive() || jsonProp.hasInjectableValueId()) {
51
+ var paramVal = if (! isMissing || paramDef.isPrimitive || jsonProp.hasInjectableValueId()) {
68
52
val tempParamVal = buffer.getParameter(jsonProp)
69
53
if (nullIsSameAsDefault && tempParamVal == null && paramDef.isOptional) {
70
54
return @forEachIndexed
71
55
}
72
56
tempParamVal
73
57
} else {
74
- if (paramDef.type.isMarkedNullable ) {
58
+ if (paramDef.isNullable ) {
75
59
// do not try to create any object if it is nullable and the value is missing
76
60
null
77
61
} else {
@@ -84,11 +68,8 @@ internal class KotlinValueInstantiator(
84
68
paramVal = NullsAsEmptyProvider (jsonProp.valueDeserializer).getNullValue(ctxt)
85
69
}
86
70
87
- val isGenericTypeVar = paramDef.type.javaType is TypeVariable <* >
88
71
val isMissingAndRequired = paramVal == null && isMissing && jsonProp.isRequired
89
- if (isMissingAndRequired ||
90
- (! isGenericTypeVar && paramVal == null && ! paramDef.type.isMarkedNullable)
91
- ) {
72
+ if (isMissingAndRequired || (! paramDef.isGenericType && paramVal == null && ! paramDef.isNullable)) {
92
73
throw MissingKotlinParameterException (
93
74
parameter = paramDef,
94
75
processor = ctxt.parser,
@@ -97,24 +78,17 @@ internal class KotlinValueInstantiator(
97
78
}
98
79
99
80
if (strictNullChecks && paramVal != null ) {
100
- var paramType: String? = null
101
- var itemType: KType ? = null
102
- if (jsonProp.type.isCollectionLikeType && paramDef.type.arguments.getOrNull(0 )?.type?.isMarkedNullable == false && (paramVal as Collection <* >).any { it == null }) {
103
- paramType = " collection"
104
- itemType = paramDef.type.arguments[0 ].type
105
- }
106
-
107
- if (jsonProp.type.isMapLikeType && paramDef.type.arguments.getOrNull(1 )?.type?.isMarkedNullable == false && (paramVal as Map <* , * >).any { it.value == null }) {
108
- paramType = " map"
109
- itemType = paramDef.type.arguments[1 ].type
110
- }
111
-
112
- if (jsonProp.type.isArrayType && paramDef.type.arguments.getOrNull(0 )?.type?.isMarkedNullable == false && (paramVal as Array <* >).any { it == null }) {
113
- paramType = " array"
114
- itemType = paramDef.type.arguments[0 ].type
115
- }
116
-
117
- if (paramType != null && itemType != null ) {
81
+ // If an error occurs, Argument.name is always non-null
82
+ // @see com.fasterxml.jackson.module.kotlin.deser.value_instantiator.creator.Argument
83
+ when {
84
+ paramVal is Collection <* > && ! paramDef.isNullishTypeAt(0 ) && paramVal.any { it == null } ->
85
+ " collection" to paramDef.arguments[0 ].name!!
86
+ paramVal is Array <* > && ! paramDef.isNullishTypeAt(0 ) && paramVal.any { it == null } ->
87
+ " array" to paramDef.arguments[0 ].name!!
88
+ paramVal is Map <* , * > && ! paramDef.isNullishTypeAt(1 ) && paramVal.values.any { it == null } ->
89
+ " map" to paramDef.arguments[1 ].name!!
90
+ else -> null
91
+ }?.let { (paramType, itemType) ->
118
92
throw MissingKotlinParameterException (
119
93
parameter = paramDef,
120
94
processor = ctxt.parser,
@@ -123,25 +97,11 @@ internal class KotlinValueInstantiator(
123
97
}
124
98
}
125
99
126
- jsonParamValueList[numCallableParameters] = paramVal
127
- callableParameters[numCallableParameters] = paramDef
128
- numCallableParameters++
100
+ bucket[idx] = paramVal
129
101
}
130
102
131
- return if (numCallableParameters == jsonParamValueList.size && valueCreator is ConstructorValueCreator ) {
132
- // we didn't do anything special with default parameters, do a normal call
133
- super .createFromObjectWith(ctxt, jsonParamValueList)
134
- } else {
135
- valueCreator.checkAccessibility(ctxt)
136
-
137
- val callableParametersByName = linkedMapOf<KParameter , Any ?>()
138
- callableParameters.mapIndexed { idx, paramDef ->
139
- if (paramDef != null ) {
140
- callableParametersByName[paramDef] = jsonParamValueList[idx]
141
- }
142
- }
143
- valueCreator.callBy(callableParametersByName)
144
- }
103
+ valueCreator.checkAccessibility(ctxt)
104
+ return valueCreator.callBy(bucket)
145
105
}
146
106
147
107
private fun KParameter.isPrimitive (): Boolean {
0 commit comments