Skip to content

Commit

Permalink
Jackson2: Super class did not get type information (#497)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
michaelzangl authored Jul 7, 2020
1 parent c8b517c commit 8e91cd7
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ private BeanModel parseBean(SourceType<Class<?>> sourceClass, List<String> class
if (isSupported(jsonTypeInfo)) {
// this is parent
discriminantProperty = getDiscriminantPropertyName(jsonTypeInfo);
discriminantLiteral = null;
discriminantLiteral = isInterfaceOrAbstract(sourceClass.type) ? null : getTypeName(jsonTypeInfo, sourceClass.type);
} else if (isSupported(parentJsonTypeInfo = getAnnotationRecursive(sourceClass.type, JsonTypeInfo.class))) {
// this is child class
discriminantProperty = getDiscriminantPropertyName(parentJsonTypeInfo);
Expand Down Expand Up @@ -399,12 +399,16 @@ public boolean test(JsonSubTypes types) {
}
}
// use simplified class name if it's not an interface or abstract
if(!cls.isInterface() && !Modifier.isAbstract(cls.getModifiers())) {
if(!isInterfaceOrAbstract(cls)) {
return cls.getName().substring(cls.getName().lastIndexOf(".") + 1);
}
return null;
}

private boolean isInterfaceOrAbstract(Class<?> cls) {
return cls.isInterface() || Modifier.isAbstract(cls.getModifiers());
}

private static JsonSubTypes.Type getJsonSubTypeForClass(JsonSubTypes types, Class<?> cls) {
for (JsonSubTypes.Type type : types.value()) {
if (type.value().equals(cls)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@

package cz.habarta.typescript.generator;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert;
import org.junit.Test;

/**
* Test that root type name in a hirarchy is included iff root type itself is not abstract
*/
public class Jackson2DeserializableRootType {

@Test
public void testHowJacksonDeserializes() throws JsonProcessingException {
NonAbstractRoot nar = new ObjectMapper()
.readValue("{\"type\": \"rootType\"}",
NonAbstractRoot.class);
NonAbstractRoot nars = new ObjectMapper()
.readValue("{\"type\": \"subType\"}",
NonAbstractRoot.class);

Assert.assertSame(NonAbstractRoot.class, nar.getClass());
Assert.assertSame(NonAbstractRootSub.class, nars.getClass());
}

@Test
public void testRootTypeIncludedIfNotAbstract() {
final String output = new TypeScriptGenerator(TestUtils.settings()).generateTypeScript(Input.from(NonAbstractRoot.class));
Assert.assertTrue(output.contains("\"rootType\""));
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes(@JsonSubTypes.Type(NonAbstractRootSub.class))
@JsonTypeName("rootType")
public static class NonAbstractRoot {
}

@JsonTypeName("subType")
public static class NonAbstractRootSub extends NonAbstractRoot {
}

@Test
public void testRootTypeNotIncludedIfAbstract() {
final String output = new TypeScriptGenerator(TestUtils.settings()).generateTypeScript(Input.from(AbstractRoot.class));
// Root type is abstract and therefore ignored in the type list
Assert.assertFalse(output.contains("\"rootType\""));
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes(@JsonSubTypes.Type(AbstractRootSub.class))
@JsonTypeName("rootType")
public static abstract class AbstractRoot {
}

@JsonTypeName("subType")
public static class AbstractRootSub extends AbstractRoot {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public static class Order {
@JsonSubTypes.Type(Rectangle.class),
@JsonSubTypes.Type(Circle.class),
})
private static class Shape {
private abstract static class Shape {
public ShapeMetadata metadata;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private static class Geometry {
@JsonSubTypes.Type(Rectangle.class),
@JsonSubTypes.Type(Circle.class),
})
private static class Shape {
private abstract static class Shape {
}

@JsonTypeName("square")
Expand Down Expand Up @@ -127,7 +127,7 @@ private static interface DiamondC extends DiamondB1, DiamondB2 {
@JsonSubTypes.Type(DieselCar.class),
@JsonSubTypes.Type(ElectricCar.class),
})
private static class Car {
private abstract static class Car {
public String name;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class OnePossiblePropertyValueAssigningExtensionTest {
private static final String BASE_PATH = "/ext/OnePossiblePropertyValueAssigningExtensionTest-";

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "discriminator")
static class BaseClass {
abstract static class BaseClass {

@JsonProperty
private Long field1;
Expand Down Expand Up @@ -87,4 +87,4 @@ private String readResource(String suffix) {
return Utils.readString(getClass().getResourceAsStream(BASE_PATH + suffix), "\n");
}

}
}

0 comments on commit 8e91cd7

Please sign in to comment.