11package io.github.projectmapk.jackson.module.kogera.annotationIntrospector
22
3+ import com.fasterxml.jackson.annotation.JsonProperty
4+ import com.fasterxml.jackson.annotation.OptBoolean
35import com.fasterxml.jackson.databind.JavaType
46import com.fasterxml.jackson.databind.introspect.Annotated
57import com.fasterxml.jackson.databind.introspect.AnnotatedField
@@ -26,29 +28,37 @@ internal class KotlinPrimaryAnnotationIntrospector(
2628 private val nullToEmptyMap : Boolean ,
2729 private val cache : ReflectionCache
2830) : NopAnnotationIntrospector() {
31+ // If a new isRequired is explicitly specified or the old required is true, those values take precedence.
32+ // In other cases, override is done by KotlinModule.
33+ private fun JsonProperty.forceRequiredByAnnotation (): Boolean? = when {
34+ isRequired != OptBoolean .DEFAULT -> isRequired.asBoolean()
35+ required -> true
36+ else -> null
37+ }
38+
2939 // If JsonProperty.required is true, the behavior is clearly specified and the result is paramount.
3040 // Otherwise, the required is determined from the configuration and the definition on Kotlin.
3141 override fun hasRequiredMarker (m : AnnotatedMember ): Boolean? {
32- val byAnnotation = _findAnnotation (m, JSON_PROPERTY_CLASS )
33- ?.let { if (it.required) return true else false }
42+ return cache.getJmClass(m.member.declaringClass)?.let { jmClass ->
43+ // To avoid overwriting processing by other modules, annotations are checked after JmClass has been obtained
44+ _findAnnotation (m, JSON_PROPERTY_CLASS )
45+ ?.forceRequiredByAnnotation()
46+ ?.let { return it }
3447
35- return cache.getJmClass(m.member.declaringClass)?.let {
3648 when (m) {
37- is AnnotatedField -> m.hasRequiredMarker(it )
38- is AnnotatedMethod -> m.getRequiredMarkerFromCorrespondingAccessor(it )
39- is AnnotatedParameter -> m.hasRequiredMarker(it )
49+ is AnnotatedField -> m.hasRequiredMarker(jmClass )
50+ is AnnotatedMethod -> m.getRequiredMarkerFromCorrespondingAccessor(jmClass )
51+ is AnnotatedParameter -> m.hasRequiredMarker(jmClass )
4052 else -> null
4153 }
42- } ? : byAnnotation // If a JsonProperty is available, use it to reduce processing costs.
54+ }
4355 }
4456
4557 // Functions that call this may return incorrect results for value classes whose value type is Collection or Map,
4658 // but this is a rare case and difficult to handle, so it is not supported.
4759 private fun JavaType.hasDefaultEmptyValue () = (nullToEmptyCollection && isCollectionLikeType) ||
4860 (nullToEmptyMap && isMapLikeType)
4961
50- // The nullToEmpty option also affects serialization,
51- // but deserialization is preferred because there is currently no way to distinguish between contexts.
5262 private fun AnnotatedField.hasRequiredMarker (jmClass : JmClass ): Boolean? {
5363 // Direct access to `AnnotatedField` is only performed if there is no accessor (defined as JvmField),
5464 // so if an accessor is defined, it is ignored.
@@ -57,7 +67,7 @@ internal class KotlinPrimaryAnnotationIntrospector(
5767 // only a check for the existence of a getter is performed.
5868 // https://youtrack.jetbrains.com/issue/KT-6519
5969 ?.let {
60- if (it.getterName == null ) ! ( it.returnType.isNullable || type.hasDefaultEmptyValue()) else null
70+ if (it.getterName == null ) ! it.returnType.isNullable else null
6171 }
6272 }
6373
@@ -68,12 +78,8 @@ internal class KotlinPrimaryAnnotationIntrospector(
6878 ): Boolean? = when (parameterCount) {
6979 0 -> jmClass.findPropertyByGetter(member)?.isRequiredByNullability()
7080 1 -> {
71- if (this .getParameter(0 ).type.hasDefaultEmptyValue()) {
72- false
73- } else {
74- val memberSignature = member.toSignature()
75- jmClass.properties.find { it.setterSignature == memberSignature }?.isRequiredByNullability()
76- }
81+ val memberSignature = member.toSignature()
82+ jmClass.properties.find { it.setterSignature == memberSignature }?.isRequiredByNullability()
7783 }
7884 else -> null
7985 }
0 commit comments