Tatu Saloranta | 0664ac6 | 2018-04-25 15:41:19 -0700 | [diff] [blame] | 1 | package com.fasterxml.jackson.databind.jsontype; |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 2 | |
| 3 | import java.util.*; |
| 4 | |
Tatu Saloranta | bfeb1fa | 2018-05-14 16:37:35 -0700 | [diff] [blame] | 5 | import com.fasterxml.jackson.annotation.JsonProperty; |
Tatu Saloranta | 771f6c6 | 2020-02-27 19:52:22 -0800 | [diff] [blame^] | 6 | import com.fasterxml.jackson.annotation.JsonSubTypes; |
| 7 | import com.fasterxml.jackson.annotation.JsonTypeInfo; |
| 8 | |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 9 | import com.fasterxml.jackson.databind.*; |
| 10 | |
Tatu Saloranta | de6ca25 | 2018-04-19 15:01:51 -0700 | [diff] [blame] | 11 | /** |
Tatu Saloranta | 771f6c6 | 2020-02-27 19:52:22 -0800 | [diff] [blame^] | 12 | * Originally test for [databind#1964], wherein slightly incompatible type hierarchy, |
Tatu Saloranta | de6ca25 | 2018-04-19 15:01:51 -0700 | [diff] [blame] | 13 | * where `Map` key is downcast from `String` to `Object` (via use of "raw" |
| 14 | * types to force compiler to ignore incompatibility) causes exception |
| 15 | * during serialization. Although ideally code would not force round peg |
| 16 | * through square hole, it makes sense to add specific exception to allow |
| 17 | * such downcast just for Map key types (for now at least). |
| 18 | */ |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 19 | @SuppressWarnings("serial") |
Tatu Saloranta | 771f6c6 | 2020-02-27 19:52:22 -0800 | [diff] [blame^] | 20 | public class SubTypeResolutionTest extends BaseMapTest |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 21 | { |
Tatu Saloranta | bfeb1fa | 2018-05-14 16:37:35 -0700 | [diff] [blame] | 22 | // [databind#1964] |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 23 | static class AccessModel { |
Tatu Saloranta | de6ca25 | 2018-04-19 15:01:51 -0700 | [diff] [blame] | 24 | private Map<String, Collection<String>> repositoryPrivileges; |
| 25 | |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 26 | public AccessModel() { |
| 27 | repositoryPrivileges = new HashMap<>(); |
| 28 | } |
Tatu Saloranta | de6ca25 | 2018-04-19 15:01:51 -0700 | [diff] [blame] | 29 | |
| 30 | // 19-Apr-2018, tatu; this would prevent issues |
| 31 | // @JsonSerialize(typing = JsonSerialize.Typing.STATIC) |
| 32 | public Map<String, Collection<String>> getRepositoryPrivileges() { |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 33 | return repositoryPrivileges; |
| 34 | } |
Tatu Saloranta | de6ca25 | 2018-04-19 15:01:51 -0700 | [diff] [blame] | 35 | |
| 36 | public void setRepositoryPrivileges(Map<String, Collection<String>> repositoryPrivileges) { |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 37 | this.repositoryPrivileges = repositoryPrivileges; |
| 38 | } |
| 39 | } |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 40 | static class CustomMap<T> extends LinkedHashMap<Object, T> { } |
| 41 | |
Tatu Saloranta | bfeb1fa | 2018-05-14 16:37:35 -0700 | [diff] [blame] | 42 | // [databind#2034]: specialization from `Object` to other types probably should |
| 43 | // just be allowed (at least in serialization case) |
| 44 | interface Dummy { |
| 45 | List<String> getStrings(); |
| 46 | } |
| 47 | |
| 48 | static class MetaModel<M, B> extends AbstractMetaValue<M, M, B> { |
| 49 | |
| 50 | @JsonProperty |
| 51 | protected final Map<String, AbstractMetaValue<M, ?, B>> attributes = new HashMap<>(); |
| 52 | |
| 53 | public <V> ListMetaAttribute<M, V, B> describeList(final String attributeName) { |
| 54 | final ListMetaAttribute<M, V, B> metaAttribute = new ListMetaAttribute<>(); |
| 55 | attributes.put(attributeName, metaAttribute); |
| 56 | return metaAttribute; |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | static abstract class AbstractMetaValue<M, V, B> { |
| 61 | public int getBogus() { return 3; } |
| 62 | } |
| 63 | |
| 64 | static class ListMetaAttribute<M, V, B> extends MetaAttribute<M, List<V>, B> { |
| 65 | public ListMetaAttribute() { } |
| 66 | } |
| 67 | |
| 68 | static class MetaAttribute<M, V, B> extends AbstractMetaValue<M, V, B> { |
| 69 | public MetaAttribute() { } |
| 70 | } |
Tatu Saloranta | 771f6c6 | 2020-02-27 19:52:22 -0800 | [diff] [blame^] | 71 | |
| 72 | // [databind#2632]: fail to specialize type-erased |
| 73 | @SuppressWarnings("rawtypes") |
| 74 | @JsonTypeInfo(use = JsonTypeInfo.Id.NAME) |
| 75 | @JsonSubTypes(value = { |
| 76 | @JsonSubTypes.Type(value = Either.Left.class, name = "left"), |
| 77 | @JsonSubTypes.Type(value = Either.Right.class, name = "right") |
| 78 | }) |
| 79 | static class Either<L, R> { |
| 80 | static class Left<T> extends Either { } |
| 81 | static class Right<T> extends Either { } |
| 82 | } |
| 83 | |
| 84 | static class Foo { |
| 85 | @SuppressWarnings("unchecked") |
| 86 | public Either<String, String> getEither() { |
| 87 | return new Either.Right<String>(); |
| 88 | } |
| 89 | } |
| 90 | |
Tatu Saloranta | bfeb1fa | 2018-05-14 16:37:35 -0700 | [diff] [blame] | 91 | /* |
| 92 | /********************************************************************** |
| 93 | /* Unit tests |
| 94 | /********************************************************************** |
| 95 | */ |
| 96 | |
Tatu Saloranta | c7ddf69 | 2019-08-23 14:02:52 -0700 | [diff] [blame] | 97 | final ObjectMapper MAPPER = newJsonMapper(); |
Tatu Saloranta | bfeb1fa | 2018-05-14 16:37:35 -0700 | [diff] [blame] | 98 | |
| 99 | // [databind#1964] |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 100 | public void testTypeCompatibility1964() throws Exception |
| 101 | { |
Tatu Saloranta | de6ca25 | 2018-04-19 15:01:51 -0700 | [diff] [blame] | 102 | // Important! Must use raw type since assignment requires effectively |
| 103 | // casting due incompatible type parameters. |
Tatu Saloranta | fbe64a2 | 2018-05-03 20:40:56 -0700 | [diff] [blame] | 104 | @SuppressWarnings({ "unchecked", "rawtypes" }) |
Tatu Saloranta | de6ca25 | 2018-04-19 15:01:51 -0700 | [diff] [blame] | 105 | Map<String, Collection<String>> repoPrivilegesMap = new CustomMap(); |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 106 | String key = "/storages/storage0/releases"; |
| 107 | Collection<String> values = new HashSet<>(); |
| 108 | values.add("ARTIFACTS_RESOLVE"); |
| 109 | repoPrivilegesMap.put(key, values); |
| 110 | |
| 111 | AccessModel accessModel = new AccessModel(); |
| 112 | accessModel.setRepositoryPrivileges(repoPrivilegesMap); |
| 113 | |
Tatu Saloranta | bfeb1fa | 2018-05-14 16:37:35 -0700 | [diff] [blame] | 114 | String jsonStr = MAPPER.writeValueAsString(accessModel); |
| 115 | // ... could/should verify more, perhaps, but for now let it be. |
| 116 | assertNotNull(jsonStr); |
| 117 | } |
| 118 | |
| 119 | // [databind#2034] |
| 120 | public void testTypeSpecialization2034() throws Exception |
| 121 | { |
| 122 | MetaModel<Dummy, Dummy> metaModel = new MetaModel<>(); |
| 123 | metaModel.describeList("a1"); |
| 124 | String jsonStr = MAPPER.writeValueAsString(metaModel); |
Tatu Saloranta | de6ca25 | 2018-04-19 15:01:51 -0700 | [diff] [blame] | 125 | // ... could/should verify more, perhaps, but for now let it be. |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 126 | assertNotNull(jsonStr); |
| 127 | } |
Tatu Saloranta | 771f6c6 | 2020-02-27 19:52:22 -0800 | [diff] [blame^] | 128 | |
| 129 | // [databind#2632]: fail to specialize type-erased |
| 130 | public void testSpecializeIncompatibleRawType() throws Exception |
| 131 | { |
| 132 | // 27-Feb-2020, tatu: First things first; incompatible typing should |
| 133 | // cause reasonable exception |
| 134 | // ... although since it's writing, perhaps should NOT fail at all? |
| 135 | String json; |
| 136 | |
| 137 | try { |
| 138 | json = MAPPER.writeValueAsString(new Foo()); |
| 139 | assertNotNull(json); |
| 140 | fail("Should not (yet?) pass"); |
| 141 | } catch (JsonMappingException e) { |
| 142 | verifyException(e, "Failed to specialize base type "); |
| 143 | } |
| 144 | } |
Tatu Saloranta | 09e5ba1 | 2018-04-05 20:14:35 -0700 | [diff] [blame] | 145 | } |