Skip to content

Commit 8e91cd7

Browse files
authored
Jackson2: Super class did not get type information (#497)
* Jackson2: Classes with type info annotation can be used as type if they are not abstract. * Mark test classes that should not be deserializable as abstract.
1 parent c8b517c commit 8e91cd7

File tree

5 files changed

+73
-7
lines changed

5 files changed

+73
-7
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ private BeanModel parseBean(SourceType<Class<?>> sourceClass, List<String> class
253253
if (isSupported(jsonTypeInfo)) {
254254
// this is parent
255255
discriminantProperty = getDiscriminantPropertyName(jsonTypeInfo);
256-
discriminantLiteral = null;
256+
discriminantLiteral = isInterfaceOrAbstract(sourceClass.type) ? null : getTypeName(jsonTypeInfo, sourceClass.type);
257257
} else if (isSupported(parentJsonTypeInfo = getAnnotationRecursive(sourceClass.type, JsonTypeInfo.class))) {
258258
// this is child class
259259
discriminantProperty = getDiscriminantPropertyName(parentJsonTypeInfo);
@@ -399,12 +399,16 @@ public boolean test(JsonSubTypes types) {
399399
}
400400
}
401401
// use simplified class name if it's not an interface or abstract
402-
if(!cls.isInterface() && !Modifier.isAbstract(cls.getModifiers())) {
402+
if(!isInterfaceOrAbstract(cls)) {
403403
return cls.getName().substring(cls.getName().lastIndexOf(".") + 1);
404404
}
405405
return null;
406406
}
407407

408+
private boolean isInterfaceOrAbstract(Class<?> cls) {
409+
return cls.isInterface() || Modifier.isAbstract(cls.getModifiers());
410+
}
411+
408412
private static JsonSubTypes.Type getJsonSubTypeForClass(JsonSubTypes types, Class<?> cls) {
409413
for (JsonSubTypes.Type type : types.value()) {
410414
if (type.value().equals(cls)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
2+
package cz.habarta.typescript.generator;
3+
4+
import com.fasterxml.jackson.annotation.JsonSubTypes;
5+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
6+
import com.fasterxml.jackson.annotation.JsonTypeName;
7+
import com.fasterxml.jackson.core.JsonProcessingException;
8+
import com.fasterxml.jackson.databind.ObjectMapper;
9+
import org.junit.Assert;
10+
import org.junit.Test;
11+
12+
/**
13+
* Test that root type name in a hirarchy is included iff root type itself is not abstract
14+
*/
15+
public class Jackson2DeserializableRootType {
16+
17+
@Test
18+
public void testHowJacksonDeserializes() throws JsonProcessingException {
19+
NonAbstractRoot nar = new ObjectMapper()
20+
.readValue("{\"type\": \"rootType\"}",
21+
NonAbstractRoot.class);
22+
NonAbstractRoot nars = new ObjectMapper()
23+
.readValue("{\"type\": \"subType\"}",
24+
NonAbstractRoot.class);
25+
26+
Assert.assertSame(NonAbstractRoot.class, nar.getClass());
27+
Assert.assertSame(NonAbstractRootSub.class, nars.getClass());
28+
}
29+
30+
@Test
31+
public void testRootTypeIncludedIfNotAbstract() {
32+
final String output = new TypeScriptGenerator(TestUtils.settings()).generateTypeScript(Input.from(NonAbstractRoot.class));
33+
Assert.assertTrue(output.contains("\"rootType\""));
34+
}
35+
36+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
37+
@JsonSubTypes(@JsonSubTypes.Type(NonAbstractRootSub.class))
38+
@JsonTypeName("rootType")
39+
public static class NonAbstractRoot {
40+
}
41+
42+
@JsonTypeName("subType")
43+
public static class NonAbstractRootSub extends NonAbstractRoot {
44+
}
45+
46+
@Test
47+
public void testRootTypeNotIncludedIfAbstract() {
48+
final String output = new TypeScriptGenerator(TestUtils.settings()).generateTypeScript(Input.from(AbstractRoot.class));
49+
// Root type is abstract and therefore ignored in the type list
50+
Assert.assertFalse(output.contains("\"rootType\""));
51+
}
52+
53+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
54+
@JsonSubTypes(@JsonSubTypes.Type(AbstractRootSub.class))
55+
@JsonTypeName("rootType")
56+
public static abstract class AbstractRoot {
57+
}
58+
59+
@JsonTypeName("subType")
60+
public static class AbstractRootSub extends AbstractRoot {
61+
}
62+
}

typescript-generator-core/src/test/java/cz/habarta/typescript/generator/JsonDeserializationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public static class Order {
148148
@JsonSubTypes.Type(Rectangle.class),
149149
@JsonSubTypes.Type(Circle.class),
150150
})
151-
private static class Shape {
151+
private abstract static class Shape {
152152
public ShapeMetadata metadata;
153153
}
154154

typescript-generator-core/src/test/java/cz/habarta/typescript/generator/TaggedUnionsTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ private static class Geometry {
2323
@JsonSubTypes.Type(Rectangle.class),
2424
@JsonSubTypes.Type(Circle.class),
2525
})
26-
private static class Shape {
26+
private abstract static class Shape {
2727
}
2828

2929
@JsonTypeName("square")
@@ -127,7 +127,7 @@ private static interface DiamondC extends DiamondB1, DiamondB2 {
127127
@JsonSubTypes.Type(DieselCar.class),
128128
@JsonSubTypes.Type(ElectricCar.class),
129129
})
130-
private static class Car {
130+
private abstract static class Car {
131131
public String name;
132132
}
133133

typescript-generator-core/src/test/java/cz/habarta/typescript/generator/ext/OnePossiblePropertyValueAssigningExtensionTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class OnePossiblePropertyValueAssigningExtensionTest {
1818
private static final String BASE_PATH = "/ext/OnePossiblePropertyValueAssigningExtensionTest-";
1919

2020
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "discriminator")
21-
static class BaseClass {
21+
abstract static class BaseClass {
2222

2323
@JsonProperty
2424
private Long field1;
@@ -87,4 +87,4 @@ private String readResource(String suffix) {
8787
return Utils.readString(getClass().getResourceAsStream(BASE_PATH + suffix), "\n");
8888
}
8989

90-
}
90+
}

0 commit comments

Comments
 (0)