Skip to content

Commit d5d7652

Browse files
authored
Merge pull request #240 from shartte/sealed-class-subtypes
Discover Subclasses of a sealed class automatically
2 parents b2183ab + f3c29d1 commit d5d7652

File tree

2 files changed

+95
-5
lines changed

2 files changed

+95
-5
lines changed

src/main/kotlin/com/fasterxml/jackson/module/kotlin/KotlinAnnotationIntrospector.kt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@ package com.fasterxml.jackson.module.kotlin
33
import com.fasterxml.jackson.annotation.JsonProperty
44
import com.fasterxml.jackson.databind.DeserializationFeature
55
import com.fasterxml.jackson.databind.Module
6-
import com.fasterxml.jackson.databind.introspect.AnnotatedField
7-
import com.fasterxml.jackson.databind.introspect.AnnotatedMember
8-
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod
9-
import com.fasterxml.jackson.databind.introspect.AnnotatedParameter
10-
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector
6+
import com.fasterxml.jackson.databind.introspect.*
7+
import com.fasterxml.jackson.databind.jsontype.NamedType
118
import java.lang.reflect.Constructor
129
import java.lang.reflect.Field
1310
import java.lang.reflect.Method
@@ -41,6 +38,26 @@ internal class KotlinAnnotationIntrospector(private val context: Module.SetupCon
4138
}
4239
}
4340

41+
/**
42+
* Subclasses can be detected automatically for sealed classes, since all possible subclasses are known
43+
* at compile-time to Kotlin. This makes [com.fasterxml.jackson.annotation.JsonSubTypes] redundant.
44+
*/
45+
override fun findSubtypes(a: Annotated): MutableList<NamedType>? {
46+
47+
val rawType = a.rawType
48+
if (rawType.isKotlinClass()) {
49+
val kClass = rawType.kotlin
50+
if (kClass.isSealed) {
51+
return kClass.sealedSubclasses
52+
.map { NamedType(it.java) }
53+
.toMutableList()
54+
}
55+
}
56+
57+
return null
58+
59+
}
60+
4461
private fun AnnotatedField.hasRequiredMarker(): Boolean? {
4562
val byAnnotation = (member as Field).getAnnotationsByType(JsonProperty::class.java).firstOrNull()?.required
4663
val byNullability = (member as Field).kotlinProperty?.returnType?.isRequired()
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.fasterxml.jackson.module.kotlin.test
2+
3+
import com.fasterxml.jackson.annotation.JsonSubTypes
4+
import com.fasterxml.jackson.annotation.JsonTypeInfo
5+
import com.fasterxml.jackson.annotation.JsonTypeName
6+
import com.fasterxml.jackson.databind.ObjectMapper
7+
import com.fasterxml.jackson.module.kotlin.KotlinModule
8+
import com.fasterxml.jackson.module.kotlin.readValue
9+
import org.junit.Test
10+
import kotlin.test.assertEquals
11+
12+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
13+
sealed class Github239Either {
14+
15+
@JsonTypeName("a")
16+
data class A(var field: String = "") : Github239Either()
17+
18+
@JsonTypeName("b")
19+
data class B(var otherField: String = "") : Github239Either()
20+
21+
}
22+
23+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
24+
@JsonSubTypes(
25+
JsonSubTypes.Type(Github239EitherCustomized.A::class, name = "a"),
26+
JsonSubTypes.Type(Github239EitherCustomized.B::class, name = "b")
27+
)
28+
sealed class Github239EitherCustomized {
29+
30+
data class A(var field: String = "") : Github239EitherCustomized()
31+
32+
data class B(var otherField: String = "") : Github239EitherCustomized()
33+
34+
}
35+
36+
class TestGithub239 {
37+
val json = """[
38+
{
39+
"@type": "a",
40+
"field": "value"
41+
},
42+
{
43+
"@type": "b",
44+
"otherField": "1234"
45+
}
46+
]"""
47+
48+
val mapper = ObjectMapper()
49+
.registerModule(KotlinModule())
50+
51+
@Test
52+
fun test_implicit_subclasses() {
53+
54+
val array = mapper.readValue<Array<Github239Either>>(json)
55+
56+
assertEquals(2, array.size)
57+
assertEquals(Github239Either.A("value"), array[0])
58+
assertEquals(Github239Either.B("1234"), array[1])
59+
60+
}
61+
62+
@Test
63+
fun test_explicit_subclasses() {
64+
65+
val array = mapper.readValue<Array<Github239EitherCustomized>>(json)
66+
67+
assertEquals(2, array.size)
68+
assertEquals(Github239EitherCustomized.A("value"), array[0])
69+
assertEquals(Github239EitherCustomized.B("1234"), array[1])
70+
71+
}
72+
73+
}

0 commit comments

Comments
 (0)