Skip to content

Commit b957f29

Browse files
committed
improvement: Support minimal definitions for tagged unions
Previously, this library only supported `Id.NAME` and `Id.CLASS` for `@JsonTypeInfo`, however, since inception, `Id.MINIMAL_CLASS` and `Id.SIMPLE_NAME` have been introduced, which allows us to write less redundant code, and have a more compact representation. While `Id.SIMPLE_NAME` is not in Jackson bom 2.15.2 (which is what this project uses), `Id.MINIMAL_CLASS` is. I use Jackson 2.18+, and would like to use the `SIMPLE_NAME` representation, instead of manually annotating thousands of classes, I would prefer to support the minimal definition for sealed interfaces/classes. This commit makes a more forward compatible method of determining if a tagged union is being used, and instead of only allowing certain uses, it, instead, disallows known non-functional usages.
1 parent 2c6bb61 commit b957f29

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/parser/Jackson2Parser.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,11 @@ public Jackson2Parser create(Settings settings, TypeProcessor commonTypeProcesso
108108
}
109109

110110
public static class JaxbParserFactory extends Jackson2ParserFactory {
111-
111+
112112
public JaxbParserFactory() {
113113
super(true);
114114
}
115-
115+
116116
}
117117

118118
private final ObjectMapper objectMapper = new ObjectMapper();
@@ -423,12 +423,22 @@ private Type processIdentity(Type propertyType, BeanProperty beanProperty) {
423423
private boolean isTaggedUnion(Pair<Class<?>, JsonTypeInfo> classWithJsonTypeInfo) {
424424
final Class<?> cls = classWithJsonTypeInfo.getValue1();
425425
final JsonTypeInfo jsonTypeInfo = classWithJsonTypeInfo.getValue2();
426-
if (cls == null || Utils.hasAnyAnnotation(cls::getAnnotation, settings.disableTaggedUnionAnnotations)) {
426+
if (cls == null || Utils.hasAnyAnnotation(cls::getAnnotation, settings.disableTaggedUnionAnnotations) || jsonTypeInfo == null) {
427+
return false;
428+
}
429+
// We only support PROPERTY and EXISTING_PROPERTY for tagged unions
430+
if(jsonTypeInfo.include() != JsonTypeInfo.As.PROPERTY && jsonTypeInfo.include() != JsonTypeInfo.As.EXISTING_PROPERTY) {
431+
return false;
432+
}
433+
// We don't support NONE, DEDUCTION, or CUSTOM for tagged unions
434+
if(
435+
jsonTypeInfo.use() == JsonTypeInfo.Id.NONE ||
436+
jsonTypeInfo.use() == JsonTypeInfo.Id.DEDUCTION ||
437+
jsonTypeInfo.use() == JsonTypeInfo.Id.CUSTOM
438+
) {
427439
return false;
428440
}
429-
return jsonTypeInfo != null &&
430-
(jsonTypeInfo.include() == JsonTypeInfo.As.PROPERTY || jsonTypeInfo.include() == JsonTypeInfo.As.EXISTING_PROPERTY) &&
431-
(jsonTypeInfo.use() == JsonTypeInfo.Id.NAME || jsonTypeInfo.use() == JsonTypeInfo.Id.CLASS);
441+
return true;
432442
}
433443

434444
private boolean isDiscriminantPropertySynthetic(JsonTypeInfo jsonTypeInfo) {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package cz.habarta.typescript.generator
2+
3+
import com.fasterxml.jackson.annotation.JsonTypeInfo
4+
import org.junit.jupiter.api.Assertions
5+
import org.junit.jupiter.api.Test
6+
7+
class KotlinTaggedUnionsTest {
8+
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)
9+
sealed interface MinimalEffort {
10+
data class A(
11+
val a: String
12+
) : MinimalEffort
13+
14+
data object B : MinimalEffort
15+
}
16+
17+
@Test
18+
fun testMinimalEffortUnions() {
19+
val settings = TestUtils.settings()
20+
settings.quotes = "'"
21+
val output = TypeScriptGenerator(settings)
22+
.generateTypeScript(
23+
Input.from(
24+
MinimalEffort::class.java,
25+
MinimalEffort.A::class.java,
26+
MinimalEffort.B::class.java
27+
)
28+
)
29+
val expected = """
30+
interface MinimalEffort {
31+
'@c': 'cz.habarta.typescript.generator.KotlinTaggedUnionsTest${'$'}MinimalEffort${'$'}A' | 'cz.habarta.typescript.generator.KotlinTaggedUnionsTest${'$'}MinimalEffort${'$'}B';
32+
}
33+
34+
interface A extends MinimalEffort {
35+
'@c': 'cz.habarta.typescript.generator.KotlinTaggedUnionsTest${'$'}MinimalEffort${'$'}A';
36+
a: string;
37+
}
38+
39+
interface B extends MinimalEffort {
40+
'@c': 'cz.habarta.typescript.generator.KotlinTaggedUnionsTest${'$'}MinimalEffort${'$'}B';
41+
}
42+
""".trimIndent()
43+
Assertions.assertEquals(expected.trim(), output.trim())
44+
}
45+
}

0 commit comments

Comments
 (0)