1 package com.fasterxml.jackson.databind.module; 2 3 import java.util.*; 4 5 import com.fasterxml.jackson.databind.*; 6 import com.fasterxml.jackson.databind.deser.Deserializers; 7 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; 8 import com.fasterxml.jackson.databind.type.*; 9 10 /** 11 * Simple implementation {@link Deserializers} which allows registration of 12 * deserializers based on raw (type erased class). 13 * It can work well for basic bean and scalar type deserializers, but is not 14 * a good fit for handling generic types (like {@link Map}s and {@link Collection}s 15 * or array types). 16 *<p> 17 * Unlike {@link SimpleSerializers}, this class does not currently support generic mappings; 18 * all mappings must be to exact declared deserialization type. 19 */ 20 public class SimpleDeserializers 21 extends Deserializers.Base 22 implements java.io.Serializable 23 { 24 private static final long serialVersionUID = 1L; 25 26 protected HashMap<ClassKey,JsonDeserializer<?>> _classMappings = null; 27 28 /** 29 * Flag to help find "generic" enum deserializer, if one has been registered. 30 * 31 * @since 2.3 32 */ 33 protected boolean _hasEnumDeserializer = false; 34 35 /* 36 /********************************************************** 37 /* Life-cycle, construction and configuring 38 /********************************************************** 39 */ 40 SimpleDeserializers()41 public SimpleDeserializers() { } 42 43 /** 44 * @since 2.1 45 */ SimpleDeserializers(Map<Class<?>,JsonDeserializer<?>> desers)46 public SimpleDeserializers(Map<Class<?>,JsonDeserializer<?>> desers) { 47 addDeserializers(desers); 48 } 49 addDeserializer(Class<T> forClass, JsonDeserializer<? extends T> deser)50 public <T> void addDeserializer(Class<T> forClass, JsonDeserializer<? extends T> deser) 51 { 52 ClassKey key = new ClassKey(forClass); 53 if (_classMappings == null) { 54 _classMappings = new HashMap<ClassKey,JsonDeserializer<?>>(); 55 } 56 _classMappings.put(key, deser); 57 // [Issue#227]: generic Enum deserializer? 58 if (forClass == Enum.class) { 59 _hasEnumDeserializer = true; 60 } 61 } 62 63 /** 64 * @since 2.1 65 */ 66 @SuppressWarnings("unchecked") addDeserializers(Map<Class<?>,JsonDeserializer<?>> desers)67 public void addDeserializers(Map<Class<?>,JsonDeserializer<?>> desers) 68 { 69 for (Map.Entry<Class<?>,JsonDeserializer<?>> entry : desers.entrySet()) { 70 Class<?> cls = entry.getKey(); 71 // what a mess... nominal generics safety... 72 JsonDeserializer<Object> deser = (JsonDeserializer<Object>) entry.getValue(); 73 addDeserializer((Class<Object>) cls, deser); 74 } 75 } 76 77 /* 78 /********************************************************** 79 /* Serializers implementation 80 /********************************************************** 81 */ 82 83 @Override findArrayDeserializer(ArrayType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)84 public JsonDeserializer<?> findArrayDeserializer(ArrayType type, 85 DeserializationConfig config, BeanDescription beanDesc, 86 TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) 87 throws JsonMappingException 88 { 89 return _find(type); 90 } 91 92 @Override findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc)93 public JsonDeserializer<?> findBeanDeserializer(JavaType type, 94 DeserializationConfig config, BeanDescription beanDesc) 95 throws JsonMappingException 96 { 97 return _find(type); 98 } 99 100 @Override findCollectionDeserializer(CollectionType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)101 public JsonDeserializer<?> findCollectionDeserializer(CollectionType type, 102 DeserializationConfig config, BeanDescription beanDesc, 103 TypeDeserializer elementTypeDeserializer, 104 JsonDeserializer<?> elementDeserializer) 105 throws JsonMappingException 106 { 107 return _find(type); 108 } 109 110 @Override findCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)111 public JsonDeserializer<?> findCollectionLikeDeserializer(CollectionLikeType type, 112 DeserializationConfig config, BeanDescription beanDesc, 113 TypeDeserializer elementTypeDeserializer, 114 JsonDeserializer<?> elementDeserializer) 115 throws JsonMappingException 116 { 117 return _find(type); 118 } 119 120 @Override findEnumDeserializer(Class<?> type, DeserializationConfig config, BeanDescription beanDesc)121 public JsonDeserializer<?> findEnumDeserializer(Class<?> type, 122 DeserializationConfig config, BeanDescription beanDesc) 123 throws JsonMappingException 124 { 125 if (_classMappings == null) { 126 return null; 127 } 128 JsonDeserializer<?> deser = _classMappings.get(new ClassKey(type)); 129 if (deser == null) { 130 // 29-Sep-2019, tatu: Not 100% sure this is workable logic but leaving 131 // as is (wrt [databind#2457]. Probably works ok since this covers direct 132 // sub-classes of `Enum`; but even if custom sub-classes aren't, unlikely 133 // mapping for those ever requested for deserialization 134 if (_hasEnumDeserializer && type.isEnum()) { 135 deser = _classMappings.get(new ClassKey(Enum.class)); 136 } 137 } 138 return deser; 139 } 140 141 @Override findTreeNodeDeserializer(Class<? extends JsonNode> nodeType, DeserializationConfig config, BeanDescription beanDesc)142 public JsonDeserializer<?> findTreeNodeDeserializer(Class<? extends JsonNode> nodeType, 143 DeserializationConfig config, BeanDescription beanDesc) 144 throws JsonMappingException 145 { 146 if (_classMappings == null) { 147 return null; 148 } 149 return _classMappings.get(new ClassKey(nodeType)); 150 } 151 152 @Override findReferenceDeserializer(ReferenceType refType, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer contentTypeDeserializer, JsonDeserializer<?> contentDeserializer)153 public JsonDeserializer<?> findReferenceDeserializer(ReferenceType refType, 154 DeserializationConfig config, BeanDescription beanDesc, 155 TypeDeserializer contentTypeDeserializer, JsonDeserializer<?> contentDeserializer) 156 throws JsonMappingException { 157 // 21-Oct-2015, tatu: Unlikely this will really get used (reference types need more 158 // work, simple registration probably not sufficient). But whatever. 159 return _find(refType); 160 } 161 162 @Override findMapDeserializer(MapType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)163 public JsonDeserializer<?> findMapDeserializer(MapType type, 164 DeserializationConfig config, BeanDescription beanDesc, 165 KeyDeserializer keyDeserializer, 166 TypeDeserializer elementTypeDeserializer, 167 JsonDeserializer<?> elementDeserializer) 168 throws JsonMappingException 169 { 170 return _find(type); 171 } 172 173 @Override findMapLikeDeserializer(MapLikeType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)174 public JsonDeserializer<?> findMapLikeDeserializer(MapLikeType type, 175 DeserializationConfig config, BeanDescription beanDesc, 176 KeyDeserializer keyDeserializer, 177 TypeDeserializer elementTypeDeserializer, 178 JsonDeserializer<?> elementDeserializer) 179 throws JsonMappingException 180 { 181 return _find(type); 182 } 183 184 @Override // since 2.11 hasDeserializerFor(DeserializationConfig config, Class<?> valueType)185 public boolean hasDeserializerFor(DeserializationConfig config, 186 Class<?> valueType) { 187 return (_classMappings != null) 188 && _classMappings.containsKey(new ClassKey(valueType)); 189 } 190 _find(JavaType type)191 private final JsonDeserializer<?> _find(JavaType type) { 192 if (_classMappings == null) { 193 return null; 194 } 195 return _classMappings.get(new ClassKey(type.getRawClass())); 196 } 197 } 198