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     
41     public SimpleDeserializers() { }
42
43     /**
44      * @since 2.1
45      */

46     public SimpleDeserializers(Map<Class<?>,JsonDeserializer<?>> desers) {
47         addDeserializers(desers);
48     }
49     
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")
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
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
93     public JsonDeserializer<?> findBeanDeserializer(JavaType type,
94             DeserializationConfig config, BeanDescription beanDesc)
95         throws JsonMappingException
96     {
97         return _find(type);
98     }
99
100     @Override
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
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
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
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
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
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
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
185     public boolean hasDeserializerFor(DeserializationConfig config,
186             Class<?> valueType) {
187         return (_classMappings != null)
188                 && _classMappings.containsKey(new ClassKey(valueType));
189     }
190
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