Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Contributors:
# 2.18.4 (not yet released)

WrongWrong (@k163377)
* #923: Fixed hasRequiredMarker to only process content defined in Kotlin
* #920: Minor refactors that do not affect behavior

# 2.18.3 (28-Feb-2025)
Expand Down
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Co-maintainers:

2.18.4 (not yet released)

#923: Fixed a problem where the result of processing `hasRequiredMarker ` by a `KotlinModule` would also apply to
classes defined in `Java` when `NullToEmptyCollection` or `NullToEmptyMap` was enabled.
#920: Minor refactorings were made that did not affect behavior.

2.18.3 (28-Feb-2025)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ internal class KotlinAnnotationIntrospector(
// TODO: implement nullIsSameAsDefault flag, which represents when TRUE that if something has a default value, it can be passed a null to default it
// this likely impacts this class to be accurate about what COULD be considered required

override fun hasRequiredMarker(m: AnnotatedMember): Boolean? {
val hasRequired = cache.javaMemberIsRequired(m) {
override fun hasRequiredMarker(
m: AnnotatedMember
): Boolean? = m.takeIf { it.member.declaringClass.isKotlinClass() }?.let { _ ->
cache.javaMemberIsRequired(m) {
try {
when {
nullToEmptyCollection && m.type.isCollectionLikeType -> false
Expand All @@ -54,7 +56,6 @@ internal class KotlinAnnotationIntrospector(
null
}
}
return hasRequired
}

override fun findSerializationConverter(a: Annotated): Converter<*, *>? = when (a) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.fasterxml.jackson.module.kotlin.test.github

import com.fasterxml.jackson.databind.BeanDescription
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import kotlin.test.Test
import kotlin.test.assertTrue

class GitHub922 {
private inline fun <reified T : Any> ObjectMapper.introspectSerialization(): BeanDescription =
serializationConfig.introspect(serializationConfig.constructType(T::class.java))

private inline fun <reified T : Any> ObjectMapper.introspectDeserialization(): BeanDescription =
deserializationConfig.introspect(deserializationConfig.constructType(T::class.java))

private fun BeanDescription.isRequired(propertyName: String): Boolean =
this.findProperties().first { it.name == propertyName }.isRequired

@Test
fun `nullToEmpty does not override specification by Java annotation`() {
val mapper = jacksonObjectMapper {
enable(KotlinFeature.NullToEmptyCollection)
enable(KotlinFeature.NullToEmptyMap)
}

val desc = mapper.introspectDeserialization<GitHub922RequiredCollectionsDtoJava>()

assertTrue(desc.isRequired("list"))
assertTrue(desc.isRequired("map"))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.fasterxml.jackson.module.kotlin.test.github;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.List;
import java.util.Map;

public class GitHub922RequiredCollectionsDtoJava {
private final List<String> list;
private final Map<String, String> map;

@JsonCreator
public GitHub922RequiredCollectionsDtoJava(
@JsonProperty(value = "list", required = true) List<String> list,
@JsonProperty(value = "map", required = true) Map<String, String> map
) {
this.list = list;
this.map = map;
}

public List<String> getList() {
return list;
}

public Map<String, String> getMap() {
return map;
}
}