Skip to content

Commit

Permalink
Common property readout
Browse files Browse the repository at this point in the history
  • Loading branch information
k163377 committed May 3, 2021
1 parent 75a1c3e commit ace6cd0
Showing 1 changed file with 71 additions and 104 deletions.
Expand Up @@ -33,75 +33,91 @@ internal class KotlinValueInstantiator(
private val strictNullChecks: Boolean,
private val experimentalDeserializationBackend: Boolean
) : StdValueInstantiator(src) {
private fun experimentalCreateFromObjectWith(
private fun readOutParamVal(
ctxt: DeserializationContext,
props: Array<out SettableBeanProperty>,
buffer: PropertyValueBuffer
buffer: PropertyValueBuffer,
idx: Int,
paramDef: KParameter
): Any? {
val instantiator: Instantiator<*> = cacheNew.instantiatorFromJava(_withArgsCreator)
?: return super.createFromObjectWith(ctxt, props, buffer) // we cannot reflect this method so do the default Java-ish behavior
val jsonProp = props[idx]
val isMissing = !buffer.hasParameter(jsonProp)

val bucket = instantiator.generateBucket()
if (isMissing && paramDef.isOptional) {
return ABSENT_VALUE
}

instantiator.valueParameters.forEachIndexed { idx, paramDef ->
val jsonProp = props[idx]
val isMissing = !buffer.hasParameter(jsonProp)
var paramVal = if (!isMissing || paramDef.isPrimitive() || jsonProp.hasInjectableValueId()) {
val tempParamVal = buffer.getParameter(jsonProp)
if (nullIsSameAsDefault && tempParamVal == null && paramDef.isOptional) {
return ABSENT_VALUE
}
tempParamVal
} else {
// trying to get suitable "missing" value provided by deserializer
jsonProp.valueDeserializer?.getNullValue(ctxt)
}

if (isMissing && paramDef.isOptional) {
return@forEachIndexed
if (paramVal == null && ((nullToEmptyCollection && jsonProp.type.isCollectionLikeType) || (nullToEmptyMap && jsonProp.type.isMapLikeType))) {
paramVal = NullsAsEmptyProvider(jsonProp.valueDeserializer).getNullValue(ctxt)
}

val isGenericTypeVar = paramDef.type.javaType is TypeVariable<*>
val isMissingAndRequired = paramVal == null && isMissing && jsonProp.isRequired
if (isMissingAndRequired ||
(!isGenericTypeVar && paramVal == null && !paramDef.type.isMarkedNullable)) {
throw MissingKotlinParameterException(
parameter = paramDef,
processor = ctxt.parser,
msg = "Instantiation of ${this.valueTypeDesc} value failed for JSON property ${jsonProp.name} due to missing (therefore NULL) value for creator parameter ${paramDef.name} which is a non-nullable type"
).wrapWithPath(this.valueClass, jsonProp.name)
}

if (strictNullChecks && paramVal != null) {
var paramType: String? = null
var itemType: KType? = null
if (jsonProp.type.isCollectionLikeType && paramDef.type.arguments.getOrNull(0)?.type?.isMarkedNullable == false && (paramVal as Collection<*>).any { it == null }) {
paramType = "collection"
itemType = paramDef.type.arguments[0].type
}

var paramVal = if (!isMissing || paramDef.isPrimitive() || jsonProp.hasInjectableValueId()) {
val tempParamVal = buffer.getParameter(jsonProp)
if (nullIsSameAsDefault && tempParamVal == null && paramDef.isOptional) {
return@forEachIndexed
}
tempParamVal
} else {
// trying to get suitable "missing" value provided by deserializer
jsonProp.valueDeserializer?.getNullValue(ctxt)
if (jsonProp.type.isMapLikeType && paramDef.type.arguments.getOrNull(1)?.type?.isMarkedNullable == false && (paramVal as Map<*, *>).any { it.value == null }) {
paramType = "map"
itemType = paramDef.type.arguments[1].type
}

if (paramVal == null && ((nullToEmptyCollection && jsonProp.type.isCollectionLikeType) || (nullToEmptyMap && jsonProp.type.isMapLikeType))) {
paramVal = NullsAsEmptyProvider(jsonProp.valueDeserializer).getNullValue(ctxt)
if (jsonProp.type.isArrayType && paramDef.type.arguments.getOrNull(0)?.type?.isMarkedNullable == false && (paramVal as Array<*>).any { it == null }) {
paramType = "array"
itemType = paramDef.type.arguments[0].type
}

val isGenericTypeVar = paramDef.type.javaType is TypeVariable<*>
val isMissingAndRequired = paramVal == null && isMissing && jsonProp.isRequired
if (isMissingAndRequired ||
(!isGenericTypeVar && paramVal == null && !paramDef.type.isMarkedNullable)) {
if (paramType != null && itemType != null) {
throw MissingKotlinParameterException(
parameter = paramDef,
processor = ctxt.parser,
msg = "Instantiation of ${this.valueTypeDesc} value failed for JSON property ${jsonProp.name} due to missing (therefore NULL) value for creator parameter ${paramDef.name} which is a non-nullable type"
msg = "Instantiation of $itemType $paramType failed for JSON property ${jsonProp.name} due to null value in a $paramType that does not allow null values"
).wrapWithPath(this.valueClass, jsonProp.name)
}
}

if (strictNullChecks && paramVal != null) {
var paramType: String? = null
var itemType: KType? = null
if (jsonProp.type.isCollectionLikeType && paramDef.type.arguments.getOrNull(0)?.type?.isMarkedNullable == false && (paramVal as Collection<*>).any { it == null }) {
paramType = "collection"
itemType = paramDef.type.arguments[0].type
}
return paramVal
}

if (jsonProp.type.isMapLikeType && paramDef.type.arguments.getOrNull(1)?.type?.isMarkedNullable == false && (paramVal as Map<*, *>).any { it.value == null }) {
paramType = "map"
itemType = paramDef.type.arguments[1].type
}
private fun experimentalCreateFromObjectWith(
ctxt: DeserializationContext,
props: Array<out SettableBeanProperty>,
buffer: PropertyValueBuffer
): Any? {
val instantiator: Instantiator<*> = cacheNew.instantiatorFromJava(_withArgsCreator)
?: return super.createFromObjectWith(ctxt, props, buffer) // we cannot reflect this method so do the default Java-ish behavior

if (jsonProp.type.isArrayType && paramDef.type.arguments.getOrNull(0)?.type?.isMarkedNullable == false && (paramVal as Array<*>).any { it == null }) {
paramType = "array"
itemType = paramDef.type.arguments[0].type
}
val bucket = instantiator.generateBucket()

if (paramType != null && itemType != null) {
throw MissingKotlinParameterException(
parameter = paramDef,
processor = ctxt.parser,
msg = "Instantiation of $itemType $paramType failed for JSON property ${jsonProp.name} due to null value in a $paramType that does not allow null values"
).wrapWithPath(this.valueClass, jsonProp.name)
}
instantiator.valueParameters.forEachIndexed { idx, paramDef ->
val paramVal = readOutParamVal(ctxt, props, buffer, idx, paramDef)

if (paramVal === ABSENT_VALUE) { // If it is the same instance, continue.
return@forEachIndexed
}

bucket[idx] = paramVal
Expand Down Expand Up @@ -173,66 +189,12 @@ internal class KotlinValueInstantiator(
}

callable.valueParameters.forEachIndexed { idx, paramDef ->
val jsonProp = props[idx]
val isMissing = !buffer.hasParameter(jsonProp)
val paramVal = readOutParamVal(ctxt, props, buffer, idx, paramDef)

if (isMissing && paramDef.isOptional) {
if (paramVal === ABSENT_VALUE) { // If it is the same instance, continue.
return@forEachIndexed
}

var paramVal = if (!isMissing || paramDef.isPrimitive() || jsonProp.hasInjectableValueId()) {
val tempParamVal = buffer.getParameter(jsonProp)
if (nullIsSameAsDefault && tempParamVal == null && paramDef.isOptional) {
return@forEachIndexed
}
tempParamVal
} else {
// trying to get suitable "missing" value provided by deserializer
jsonProp.valueDeserializer?.getNullValue(ctxt)
}

if (paramVal == null && ((nullToEmptyCollection && jsonProp.type.isCollectionLikeType) || (nullToEmptyMap && jsonProp.type.isMapLikeType))) {
paramVal = NullsAsEmptyProvider(jsonProp.valueDeserializer).getNullValue(ctxt)
}

val isGenericTypeVar = paramDef.type.javaType is TypeVariable<*>
val isMissingAndRequired = paramVal == null && isMissing && jsonProp.isRequired
if (isMissingAndRequired ||
(!isGenericTypeVar && paramVal == null && !paramDef.type.isMarkedNullable)) {
throw MissingKotlinParameterException(
parameter = paramDef,
processor = ctxt.parser,
msg = "Instantiation of ${this.valueTypeDesc} value failed for JSON property ${jsonProp.name} due to missing (therefore NULL) value for creator parameter ${paramDef.name} which is a non-nullable type"
).wrapWithPath(this.valueClass, jsonProp.name)
}

if (strictNullChecks && paramVal != null) {
var paramType: String? = null
var itemType: KType? = null
if (jsonProp.type.isCollectionLikeType && paramDef.type.arguments.getOrNull(0)?.type?.isMarkedNullable == false && (paramVal as Collection<*>).any { it == null }) {
paramType = "collection"
itemType = paramDef.type.arguments[0].type
}

if (jsonProp.type.isMapLikeType && paramDef.type.arguments.getOrNull(1)?.type?.isMarkedNullable == false && (paramVal as Map<*, *>).any { it.value == null }) {
paramType = "map"
itemType = paramDef.type.arguments[1].type
}

if (jsonProp.type.isArrayType && paramDef.type.arguments.getOrNull(0)?.type?.isMarkedNullable == false && (paramVal as Array<*>).any { it == null }) {
paramType = "array"
itemType = paramDef.type.arguments[0].type
}

if (paramType != null && itemType != null) {
throw MissingKotlinParameterException(
parameter = paramDef,
processor = ctxt.parser,
msg = "Instantiation of $itemType $paramType failed for JSON property ${jsonProp.name} due to null value in a $paramType that does not allow null values"
).wrapWithPath(this.valueClass, jsonProp.name)
}
}

jsonParamValueList[numCallableParameters] = paramVal
callableParameters[numCallableParameters] = paramDef
numCallableParameters++
Expand Down Expand Up @@ -276,6 +238,11 @@ internal class KotlinValueInstantiator(
}

private fun SettableBeanProperty.hasInjectableValueId(): Boolean = injectableValueId != null

companion object {
// A marker indicating that the property could not be read.
private val ABSENT_VALUE = Any()
}
}

internal class KotlinInstantiators(
Expand Down

0 comments on commit ace6cd0

Please sign in to comment.