blob: 1b29a77bb9df96b5256153ca47edc3e67c65180c [file] [log] [blame]
package com.fasterxml.jackson.databind.jsontype;
import java.util.*;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.*;
/**
* Originally test for [databind#1964], wherein slightly incompatible type hierarchy,
* where `Map` key is downcast from `String` to `Object` (via use of "raw"
* types to force compiler to ignore incompatibility) causes exception
* during serialization. Although ideally code would not force round peg
* through square hole, it makes sense to add specific exception to allow
* such downcast just for Map key types (for now at least).
*/
@SuppressWarnings("serial")
public class SubTypeResolutionTest extends BaseMapTest
{
// [databind#1964]
static class AccessModel {
private Map<String, Collection<String>> repositoryPrivileges;
public AccessModel() {
repositoryPrivileges = new HashMap<>();
}
// 19-Apr-2018, tatu; this would prevent issues
// @JsonSerialize(typing = JsonSerialize.Typing.STATIC)
public Map<String, Collection<String>> getRepositoryPrivileges() {
return repositoryPrivileges;
}
public void setRepositoryPrivileges(Map<String, Collection<String>> repositoryPrivileges) {
this.repositoryPrivileges = repositoryPrivileges;
}
}
static class CustomMap<T> extends LinkedHashMap<Object, T> { }
// [databind#2034]: specialization from `Object` to other types probably should
// just be allowed (at least in serialization case)
interface Dummy {
List<String> getStrings();
}
static class MetaModel<M, B> extends AbstractMetaValue<M, M, B> {
@JsonProperty
protected final Map<String, AbstractMetaValue<M, ?, B>> attributes = new HashMap<>();
public <V> ListMetaAttribute<M, V, B> describeList(final String attributeName) {
final ListMetaAttribute<M, V, B> metaAttribute = new ListMetaAttribute<>();
attributes.put(attributeName, metaAttribute);
return metaAttribute;
}
}
static abstract class AbstractMetaValue<M, V, B> {
public int getBogus() { return 3; }
}
static class ListMetaAttribute<M, V, B> extends MetaAttribute<M, List<V>, B> {
public ListMetaAttribute() { }
}
static class MetaAttribute<M, V, B> extends AbstractMetaValue<M, V, B> {
public MetaAttribute() { }
}
// [databind#2632]: fail to specialize type-erased
@SuppressWarnings("rawtypes")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = Either.Left.class, name = "left"),
@JsonSubTypes.Type(value = Either.Right.class, name = "right")
})
static class Either<L, R> {
static class Left<T> extends Either { }
static class Right<T> extends Either { }
}
static class Foo {
@SuppressWarnings("unchecked")
public Either<String, String> getEither() {
return new Either.Right<String>();
}
}
/*
/**********************************************************************
/* Unit tests
/**********************************************************************
*/
final ObjectMapper MAPPER = newJsonMapper();
// [databind#1964]
public void testTypeCompatibility1964() throws Exception
{
// Important! Must use raw type since assignment requires effectively
// casting due incompatible type parameters.
@SuppressWarnings({ "unchecked", "rawtypes" })
Map<String, Collection<String>> repoPrivilegesMap = new CustomMap();
String key = "/storages/storage0/releases";
Collection<String> values = new HashSet<>();
values.add("ARTIFACTS_RESOLVE");
repoPrivilegesMap.put(key, values);
AccessModel accessModel = new AccessModel();
accessModel.setRepositoryPrivileges(repoPrivilegesMap);
String jsonStr = MAPPER.writeValueAsString(accessModel);
// ... could/should verify more, perhaps, but for now let it be.
assertNotNull(jsonStr);
}
// [databind#2034]
public void testTypeSpecialization2034() throws Exception
{
MetaModel<Dummy, Dummy> metaModel = new MetaModel<>();
metaModel.describeList("a1");
String jsonStr = MAPPER.writeValueAsString(metaModel);
// ... could/should verify more, perhaps, but for now let it be.
assertNotNull(jsonStr);
}
// [databind#2632]: fail to specialize type-erased
public void testSpecializeIncompatibleRawType() throws Exception
{
// 27-Feb-2020, tatu: First things first; incompatible typing should
// cause reasonable exception
// ... although since it's writing, perhaps should NOT fail at all?
String json;
try {
json = MAPPER.writeValueAsString(new Foo());
assertNotNull(json);
fail("Should not (yet?) pass");
} catch (JsonMappingException e) {
verifyException(e, "Failed to specialize base type ");
}
}
}