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> repositoryPrivileges; public AccessModel() { repositoryPrivileges = new HashMap<>(); } // 19-Apr-2018, tatu; this would prevent issues // @JsonSerialize(typing = JsonSerialize.Typing.STATIC) public Map> getRepositoryPrivileges() { return repositoryPrivileges; } public void setRepositoryPrivileges(Map> repositoryPrivileges) { this.repositoryPrivileges = repositoryPrivileges; } } static class CustomMap extends LinkedHashMap { } // [databind#2034]: specialization from `Object` to other types probably should // just be allowed (at least in serialization case) interface Dummy { List getStrings(); } static class MetaModel extends AbstractMetaValue { @JsonProperty protected final Map> attributes = new HashMap<>(); public ListMetaAttribute describeList(final String attributeName) { final ListMetaAttribute metaAttribute = new ListMetaAttribute<>(); attributes.put(attributeName, metaAttribute); return metaAttribute; } } static abstract class AbstractMetaValue { public int getBogus() { return 3; } } static class ListMetaAttribute extends MetaAttribute, B> { public ListMetaAttribute() { } } static class MetaAttribute extends AbstractMetaValue { 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 { static class Left extends Either { } static class Right extends Either { } } static class Foo { @SuppressWarnings("unchecked") public Either getEither() { return new Either.Right(); } } /* /********************************************************************** /* 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> repoPrivilegesMap = new CustomMap(); String key = "/storages/storage0/releases"; Collection 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 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 { String json = MAPPER.writeValueAsString(new Foo()); assertNotNull(json); } }