Skip to content

Commit 0303f98

Browse files
committed
check for repeated logical subtype names FasterXML#3500
1 parent da8bd5f commit 0303f98

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java

+33
Original file line numberDiff line numberDiff line change
@@ -621,14 +621,47 @@ public List<NamedType> findSubtypes(Annotated a)
621621
JsonSubTypes t = _findAnnotation(a, JsonSubTypes.class);
622622
if (t == null) return null;
623623
JsonSubTypes.Type[] types = t.value();
624+
625+
if (t.allowRepeatedNames()) {
626+
ArrayList<NamedType> result = new ArrayList<NamedType>(types.length);
627+
for (JsonSubTypes.Type type : types) {
628+
result.add(new NamedType(type.value(), type.name()));
629+
// [databind#2761]: alternative set of names to use
630+
for (String name : type.names()) {
631+
result.add(new NamedType(type.value(), name));
632+
}
633+
}
634+
return result;
635+
} else {
636+
return findSubtypesCheckRepeatedNames(a.getName(), types);
637+
}
638+
}
639+
640+
private List<NamedType> findSubtypesCheckRepeatedNames(String annotatedTypeName, JsonSubTypes.Type[] types)
641+
{
624642
ArrayList<NamedType> result = new ArrayList<NamedType>(types.length);
643+
Set<String> seenNames = new HashSet<>();
625644
for (JsonSubTypes.Type type : types) {
626645
result.add(new NamedType(type.value(), type.name()));
646+
647+
if (!type.name().isEmpty() && seenNames.contains(type.name())) {
648+
throw new IllegalArgumentException("Annotated type [" + annotatedTypeName + "] got repeated subtype name [" + type.name() + "]");
649+
} else {
650+
seenNames.add(type.name());
651+
}
652+
627653
// [databind#2761]: alternative set of names to use
628654
for (String name : type.names()) {
629655
result.add(new NamedType(type.value(), name));
656+
657+
if (!name.isEmpty() && seenNames.contains(name)) {
658+
throw new IllegalArgumentException("Annotated type [" + annotatedTypeName + "] got repeated subtype name [" + name + "]");
659+
} else {
660+
seenNames.add(name);
661+
}
630662
}
631663
}
664+
632665
return result;
633666
}
634667

src/test/java/com/fasterxml/jackson/databind/jsontype/TestMultipleTypeNames.java

+36
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import com.fasterxml.jackson.databind.BaseMapTest;
77
import com.fasterxml.jackson.databind.ObjectMapper;
8+
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
89
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
910

1011
import java.util.List;
@@ -72,6 +73,28 @@ static class BaseForNameAndNamesTest {
7273
public MultiTypeName getData() { return data; }
7374
}
7475

76+
static class WrapperForNotUniqueNamesTest {
77+
List<BaseForNotUniqueNamesTest> base;
78+
public List<BaseForNotUniqueNamesTest> getBase() { return base; }
79+
}
80+
81+
static class BaseForNotUniqueNamesTest {
82+
private String type;
83+
public String getType() { return type; }
84+
85+
@JsonTypeInfo(
86+
use = JsonTypeInfo.Id.NAME,
87+
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
88+
property = "type"
89+
)
90+
@JsonSubTypes(value = {
91+
@JsonSubTypes.Type(value = A.class, name = "a"),
92+
@JsonSubTypes.Type(value = B.class, names = {"b","a"}),
93+
}, allowRepeatedNames = false)
94+
MultiTypeName data;
95+
public MultiTypeName getData() { return data; }
96+
}
97+
7598
/*
7699
/**********************************************************
77100
/* Test methods
@@ -133,4 +156,17 @@ public void testNameAndNames() throws Exception
133156
verifyException(e, "Unrecognized field \"data\"");
134157
}
135158
}
159+
160+
public void testNotUniqueNameAndNames() throws Exception
161+
{
162+
String json = "{\"base\": [{\"type\":\"a\", \"data\": {\"x\": 5}}, {\"type\":\"b\", \"data\": {\"y\": 3.1}}, {\"type\":\"c\", \"data\": {\"y\": 33.8}}]}";
163+
164+
try {
165+
MAPPER.readValue(json, WrapperForNotUniqueNamesTest.class);
166+
fail("This serialisation should fail because of repeated subtype name");
167+
} catch (InvalidDefinitionException e) {
168+
verifyException(e, "Annotated type [data] got repeated subtype name [a]");
169+
}
170+
}
171+
136172
}

0 commit comments

Comments
 (0)