blob: eec32d781798e48e8c708e069d7aa84e2bc9441f [file] [log] [blame]
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001package com.fasterxml.jackson.databind;
2
3import java.io.IOException;
Tatu Saloranta06c20b12012-01-29 21:36:52 -08004import java.text.DateFormat;
5import java.text.ParseException;
Tatu Salorantad068a402016-10-05 23:21:57 -07006import java.util.*;
Tatu Salorantaaf263c32013-10-24 16:18:50 -07007import java.util.concurrent.atomic.AtomicReference;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08008
Tatu Salorantaa5301ba2015-12-11 09:47:09 -08009import com.fasterxml.jackson.annotation.JsonFormat;
Tatu Salorantad71dffa2012-02-07 21:05:21 -080010import com.fasterxml.jackson.annotation.ObjectIdGenerator;
Pascal GĂ©linas184cae32014-02-05 17:35:56 -050011import com.fasterxml.jackson.annotation.ObjectIdResolver;
Tatu Saloranta6faae872016-10-22 19:43:50 -070012
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080013import com.fasterxml.jackson.core.*;
Tatu Saloranta6faae872016-10-22 19:43:50 -070014
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -070015import com.fasterxml.jackson.databind.cfg.ContextAttributes;
Tatu Saloranta06c20b12012-01-29 21:36:52 -080016import com.fasterxml.jackson.databind.deser.*;
Tatu Saloranta9d1fb752016-06-07 22:47:04 -070017import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader;
Tatu Saloranta34a8adf2012-02-08 22:07:36 -080018import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
Tatuc3a73d02012-01-31 12:45:49 -080019import com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer;
Tatu Salorantaa0bd1592016-11-25 18:49:52 -080020import com.fasterxml.jackson.databind.exc.MismatchedInputException;
Tatu Salorantac1478ac2016-09-29 08:17:03 -070021import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
Tatu Salorantadd348562012-07-18 17:25:02 -070022import com.fasterxml.jackson.databind.exc.InvalidFormatException;
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -070023import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
Tatu Saloranta06c20b12012-01-29 21:36:52 -080024import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
Tatu Saloranta39294f92018-09-04 22:25:50 -070025import com.fasterxml.jackson.databind.exc.ValueInstantiationException;
Tatub37ff332012-01-24 16:19:36 -080026import com.fasterxml.jackson.databind.introspect.Annotated;
Tatu Salorantab3e41942019-09-11 14:18:02 -070027import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
Tatu Salorantabb06aa02016-09-08 22:38:23 -070028import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
Tatuc3a73d02012-01-31 12:45:49 -080029import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
Tatu Salorantad6230fd2016-05-30 21:11:19 -070030import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
Tatu Saloranta2f823442011-12-23 20:25:27 -080031import com.fasterxml.jackson.databind.node.JsonNodeFactory;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080032import com.fasterxml.jackson.databind.type.TypeFactory;
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -080033import com.fasterxml.jackson.databind.util.*;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080034
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080035/**
Tatu Saloranta97f84822012-01-29 21:38:40 -080036 * Context for the process of deserialization a single root-level value.
37 * Used to allow passing in configuration settings and reusable temporary
38 * objects (scrap arrays, containers).
Tatu Saloranta060ce112012-02-01 22:18:09 -080039 *<p>
Tatu Salorantac1478ac2016-09-29 08:17:03 -070040 * Instance life-cycle is such that a partially configured "blueprint" object
Tatu Saloranta060ce112012-02-01 22:18:09 -080041 * is registered with {@link ObjectMapper} (and {@link ObjectReader},
Tatu Salorantac1478ac2016-09-29 08:17:03 -070042 * and when actual instance is needed for deserialization,
43 * a fully configured instance will be created using a method in extended internal
44 * API of sub-class
Tatu Saloranta71e876b2012-02-05 19:15:48 -080045 * ({@link com.fasterxml.jackson.databind.deser.DefaultDeserializationContext#createInstance}).
Tatu Saloranta060ce112012-02-01 22:18:09 -080046 * Each instance is guaranteed to only be used from single-threaded context;
Tatu Salorantac1478ac2016-09-29 08:17:03 -070047 * instances may be reused if (and only if) no configuration has changed.
Tatu Saloranta060ce112012-02-01 22:18:09 -080048 *<p>
49 * Defined as abstract class so that implementations must define methods
50 * for reconfiguring blueprints and creating instances.
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080051 */
Tatu Saloranta060ce112012-02-01 22:18:09 -080052public abstract class DeserializationContext
Tatu Saloranta9439a312013-03-02 13:13:09 -080053 extends DatabindContext
Tatu Saloranta0e114112012-10-06 10:45:41 -070054 implements java.io.Serializable
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080055{
Cowtowncoder7fee92e2015-02-11 16:15:08 -080056 private static final long serialVersionUID = 1L; // 2.6
Tatu Saloranta0e114112012-10-06 10:45:41 -070057
Tatu Saloranta060ce112012-02-01 22:18:09 -080058 /*
59 /**********************************************************
60 /* Configuration, immutable
61 /**********************************************************
62 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -080063
Tatu Saloranta71e876b2012-02-05 19:15:48 -080064 /**
65 * Object that handle details of {@link JsonDeserializer} caching.
66 */
Tatu Saloranta060ce112012-02-01 22:18:09 -080067 protected final DeserializerCache _cache;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080068
Tatu Saloranta060ce112012-02-01 22:18:09 -080069 /*
70 /**********************************************************
71 /* Configuration, changeable via fluent factories
72 /**********************************************************
73 */
74
75 /**
76 * Read-only factory instance; exposed to let
77 * owners (<code>ObjectMapper</code>, <code>ObjectReader</code>)
78 * access it.
79 */
Tatu Salorantaaa512742012-02-22 22:51:33 -080080 protected final DeserializerFactory _factory;
81
82 /*
83 /**********************************************************
Tatu Saloranta060ce112012-02-01 22:18:09 -080084 /* Configuration that gets set for instances (not blueprints)
Tatu Saloranta71e876b2012-02-05 19:15:48 -080085 /* (partly denormalized for performance)
Tatu Saloranta060ce112012-02-01 22:18:09 -080086 /**********************************************************
87 */
88
Tatu Saloranta71e876b2012-02-05 19:15:48 -080089 /**
90 * Generic deserialization processing configuration
91 */
Tatu Saloranta060ce112012-02-01 22:18:09 -080092 protected final DeserializationConfig _config;
Tatu Saloranta71e876b2012-02-05 19:15:48 -080093
94 /**
95 * Bitmap of {@link DeserializationFeature}s that are enabled
96 */
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080097 protected final int _featureFlags;
Tatu Salorantab2d3c7d2012-01-27 21:41:48 -080098
Tatu Saloranta71e876b2012-02-05 19:15:48 -080099 /**
100 * Currently active view, if any.
101 */
Tatu Salorantab2d3c7d2012-01-27 21:41:48 -0800102 protected final Class<?> _view;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800103
104 /**
105 * Currently active parser used for deserialization.
106 * May be different from the outermost parser
107 * when content is buffered.
108 */
Tatu Salorantaf5211582012-10-05 17:09:47 -0700109 protected transient JsonParser _parser;
Tatuc3a73d02012-01-31 12:45:49 -0800110
Tatu Saloranta71e876b2012-02-05 19:15:48 -0800111 /**
112 * Object used for resolving references to injectable
113 * values.
114 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800115 protected final InjectableValues _injectableValues;
116
Tatu Saloranta060ce112012-02-01 22:18:09 -0800117 /*
118 /**********************************************************
119 /* Per-operation reusable helper objects (not for blueprints)
120 /**********************************************************
121 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800122
Tatu Salorantaf5211582012-10-05 17:09:47 -0700123 protected transient ArrayBuilders _arrayBuilders;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800124
Tatu Salorantaf5211582012-10-05 17:09:47 -0700125 protected transient ObjectBuffer _objectBuffer;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800126
Tatu Salorantaf5211582012-10-05 17:09:47 -0700127 protected transient DateFormat _dateFormat;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700128
129 /**
130 * Lazily-constructed holder for per-call attributes.
131 *
132 * @since 2.3
133 */
134 protected transient ContextAttributes _attributes;
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800135
136 /**
137 * Type of {@link JsonDeserializer} (or, more specifically,
Cowtowncoder08efeba2015-05-05 12:34:11 -0700138 * {@link ContextualDeserializer}) that is being
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800139 * contextualized currently.
140 *
141 * @since 2.5
142 */
143 protected LinkedNode<JavaType> _currentType;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800144
145 /*
146 /**********************************************************
147 /* Life-cycle
148 /**********************************************************
149 */
Tatu Saloranta060ce112012-02-01 22:18:09 -0800150
151 protected DeserializationContext(DeserializerFactory df) {
152 this(df, null);
153 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800154
Tatu Saloranta060ce112012-02-01 22:18:09 -0800155 protected DeserializationContext(DeserializerFactory df,
156 DeserializerCache cache)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800157 {
Tatu Saloranta0238e9d2019-09-12 12:53:16 -0700158 _factory = Objects.requireNonNull(df, "Cannot pass null DeserializerFactory");
Tatu Saloranta43fbd712016-11-09 21:43:27 -0800159 if (cache == null) {
160 cache = new DeserializerCache();
161 }
162 _cache = cache;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800163 _featureFlags = 0;
164 _config = null;
165 _injectableValues = null;
166 _view = null;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700167 _attributes = null;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800168 }
169
170 protected DeserializationContext(DeserializationContext src,
171 DeserializerFactory factory)
172 {
173 _cache = src._cache;
174 _factory = factory;
175
176 _config = src._config;
177 _featureFlags = src._featureFlags;
178 _view = src._view;
179 _parser = src._parser;
180 _injectableValues = src._injectableValues;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700181 _attributes = src._attributes;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800182 }
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700183
184 /**
185 * Constructor used for creating actual per-call instances.
186 */
Tatu Saloranta060ce112012-02-01 22:18:09 -0800187 protected DeserializationContext(DeserializationContext src,
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700188 DeserializationConfig config, JsonParser p,
Tatu Saloranta060ce112012-02-01 22:18:09 -0800189 InjectableValues injectableValues)
190 {
191 _cache = src._cache;
192 _factory = src._factory;
193
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800194 _config = config;
Tatu Salorantae3ae58e2012-01-28 23:08:16 -0800195 _featureFlags = config.getDeserializationFeatures();
Tatu Salorantab2d3c7d2012-01-27 21:41:48 -0800196 _view = config.getActiveView();
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700197 _parser = p;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800198 _injectableValues = injectableValues;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700199 _attributes = config.getAttributes();
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800200 }
Tatu Saloranta9439a312013-03-02 13:13:09 -0800201
Tatu Saloranta23328aa2014-10-28 22:38:15 -0700202 /**
203 * Copy-constructor for use with <code>copy()</code> by {@link ObjectMapper#copy()}
204 */
205 protected DeserializationContext(DeserializationContext src) {
206 _cache = new DeserializerCache();
207 _factory = src._factory;
208
209 _config = src._config;
210 _featureFlags = src._featureFlags;
211 _view = src._view;
212 _injectableValues = null;
213 }
214
Tatu Saloranta9439a312013-03-02 13:13:09 -0800215 /*
216 /**********************************************************
217 /* DatabindContext implementation
218 /**********************************************************
219 */
220
221 @Override
222 public DeserializationConfig getConfig() { return _config; }
223
224 @Override
225 public final Class<?> getActiveView() { return _view; }
226
227 @Override
Tatu Salorantaa5301ba2015-12-11 09:47:09 -0800228 public final boolean canOverrideAccessModifiers() {
229 return _config.canOverrideAccessModifiers();
230 }
231
232 @Override
233 public final boolean isEnabled(MapperFeature feature) {
234 return _config.isEnabled(feature);
235 }
236
237 @Override
238 public final JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType) {
239 return _config.getDefaultPropertyFormat(baseType);
240 }
Tatu Saloranta4fdbb692016-04-16 21:41:14 -0700241
Tatu Salorantaa5301ba2015-12-11 09:47:09 -0800242 @Override
Tatu Saloranta9439a312013-03-02 13:13:09 -0800243 public final AnnotationIntrospector getAnnotationIntrospector() {
244 return _config.getAnnotationIntrospector();
245 }
246
247 @Override
248 public final TypeFactory getTypeFactory() {
249 return _config.getTypeFactory();
250 }
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700251
Cowtowncoder41bbc962015-06-19 17:16:08 -0700252 /**
253 * Method for accessing default Locale to use: convenience method for
254 *<pre>
255 * getConfig().getLocale();
256 *</pre>
257 */
258 @Override
259 public Locale getLocale() {
260 return _config.getLocale();
261 }
262
263 /**
264 * Method for accessing default TimeZone to use: convenience method for
265 *<pre>
266 * getConfig().getTimeZone();
267 *</pre>
268 */
269 @Override
270 public TimeZone getTimeZone() {
271 return _config.getTimeZone();
272 }
273
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700274 /*
275 /**********************************************************
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800276 /* Access to per-call state, like generic attributes (2.3+)
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700277 /**********************************************************
278 */
279
280 @Override
281 public Object getAttribute(Object key) {
282 return _attributes.getAttribute(key);
283 }
284
285 @Override
286 public DeserializationContext setAttribute(Object key, Object value)
287 {
288 _attributes = _attributes.withPerCallAttribute(key, value);
289 return this;
290 }
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800291
292 /**
293 * Accessor to {@link JavaType} of currently contextualized
294 * {@link ContextualDeserializer}, if any.
295 * This is sometimes useful for generic {@link JsonDeserializer}s that
296 * do not get passed (or do not retain) type information when being
297 * constructed: happens for example for deserializers constructed
298 * from annotations.
299 *
300 * @since 2.5
301 *
302 * @return Type of {@link ContextualDeserializer} being contextualized,
303 * if process is on-going; null if not.
304 */
305 public JavaType getContextualType() {
306 return (_currentType == null) ? null : _currentType.value();
307 }
308
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800309 /*
310 /**********************************************************
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800311 /* Public API, config setting accessors
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800312 /**********************************************************
313 */
314
315 /**
Dmitry Katsuboe70c66f2012-09-03 16:00:30 +0200316 * Method for getting current {@link DeserializerFactory}.
317 */
318 public DeserializerFactory getFactory() {
319 return _factory;
320 }
Tatu Saloranta9439a312013-03-02 13:13:09 -0800321
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800322 /**
323 * Convenience method for checking whether specified on/off
324 * feature is enabled
325 */
Tatu9610aff2012-02-02 11:30:08 -0800326 public final boolean isEnabled(DeserializationFeature feat) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800327 /* 03-Dec-2010, tatu: minor shortcut; since this is called quite often,
328 * let's use a local copy of feature settings:
329 */
330 return (_featureFlags & feat.getMask()) != 0;
331 }
332
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800333 /**
Cowtowncoder23e52ab2015-05-19 17:53:26 -0700334 * Bulk access method for getting the bit mask of all {@link DeserializationFeature}s
335 * that are enabled.
336 *
337 * @since 2.6
338 */
339 public final int getDeserializationFeatures() {
340 return _featureFlags;
341 }
342
343 /**
344 * Bulk access method for checking that all features specified by
Tatu Saloranta0ac36ba2013-08-21 18:08:51 -0700345 * mask are enabled.
346 *
347 * @since 2.3
348 */
349 public final boolean hasDeserializationFeatures(int featureMask) {
Cowtowncoder23e52ab2015-05-19 17:53:26 -0700350 return (_featureFlags & featureMask) == featureMask;
351 }
352
353 /**
354 * Bulk access method for checking that at least one of features specified by
355 * mask is enabled.
356 *
357 * @since 2.6
358 */
359 public final boolean hasSomeOfFeatures(int featureMask) {
360 return (_featureFlags & featureMask) != 0;
Tatu Saloranta0ac36ba2013-08-21 18:08:51 -0700361 }
362
363 /**
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800364 * Method for accessing the currently active parser.
365 * May be different from the outermost parser
366 * when content is buffered.
367 *<p>
368 * Use of this method is discouraged: if code has direct access
369 * to the active parser, that should be used instead.
370 */
371 public final JsonParser getParser() { return _parser; }
372
373 public final Object findInjectableValue(Object valueId,
374 BeanProperty forProperty, Object beanInstance)
Tatu Saloranta68440372016-10-29 17:06:05 -0700375 throws JsonMappingException
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800376 {
377 if (_injectableValues == null) {
Tatu Saloranta68440372016-10-29 17:06:05 -0700378 reportBadDefinition(ClassUtil.classOf(valueId), String.format(
Oliver Kopp68476802017-06-27 22:26:41 +0300379"No 'injectableValues' configured, cannot inject value with id [%s]", valueId));
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800380 }
381 return _injectableValues.findInjectableValue(valueId, this, forProperty, beanInstance);
382 }
Tatu Salorantab2d3c7d2012-01-27 21:41:48 -0800383
Tatu Saloranta060ce112012-02-01 22:18:09 -0800384 /**
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800385 * Convenience method for accessing the default Base64 encoding
386 * used for decoding base64 encoded binary content.
387 * Same as calling:
388 *<pre>
389 * getConfig().getBase64Variant();
390 *</pre>
391 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800392 public final Base64Variant getBase64Variant() {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800393 return _config.getBase64Variant();
394 }
395
Tatu Saloranta060ce112012-02-01 22:18:09 -0800396 /**
397 * Convenience method, functionally equivalent to:
398 *<pre>
399 * getConfig().getNodeFactory();
400 * </pre>
401 */
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800402 public final JsonNodeFactory getNodeFactory() {
403 return _config.getNodeFactory();
404 }
405
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800406 /*
407 /**********************************************************
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800408 /* Public API, pass-through to DeserializerCache
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800409 /**********************************************************
410 */
Tatuc3a73d02012-01-31 12:45:49 -0800411
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800412 /**
Tatu Saloranta060ce112012-02-01 22:18:09 -0800413 * Method for checking whether we could find a deserializer
414 * for given type.
Cowtowncodera2e27202014-11-25 17:07:52 -0800415 *
Tatu Salorantaaf263c32013-10-24 16:18:50 -0700416 * @param type
417 * @since 2.3
Tatu Saloranta060ce112012-02-01 22:18:09 -0800418 */
Tatu Salorantaaf263c32013-10-24 16:18:50 -0700419 public boolean hasValueDeserializerFor(JavaType type, AtomicReference<Throwable> cause) {
420 try {
421 return _cache.hasValueDeserializerFor(this, _factory, type);
422 } catch (JsonMappingException e) {
423 if (cause != null) {
424 cause.set(e);
425 }
426 } catch (RuntimeException e) {
427 if (cause == null) { // earlier behavior
428 throw e;
429 }
430 cause.set(e);
431 }
432 return false;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800433 }
434
Tatu Saloranta060ce112012-02-01 22:18:09 -0800435 /**
Tatuc3a73d02012-01-31 12:45:49 -0800436 * Method for finding a value deserializer, and creating a contextual
437 * version if necessary, for value reached via specified property.
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800438 */
Tatuc3a73d02012-01-31 12:45:49 -0800439 @SuppressWarnings("unchecked")
440 public final JsonDeserializer<Object> findContextualValueDeserializer(JavaType type,
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700441 BeanProperty prop) throws JsonMappingException
Tatuc3a73d02012-01-31 12:45:49 -0800442 {
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700443 JsonDeserializer<Object> deser = _cache.findValueDeserializer(this, _factory, type);
Tatuc3a73d02012-01-31 12:45:49 -0800444 if (deser != null) {
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800445 deser = (JsonDeserializer<Object>) handleSecondaryContextualization(deser, prop, type);
Tatuc3a73d02012-01-31 12:45:49 -0800446 }
447 return deser;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800448 }
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700449
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800450 /**
Cowtowncodera2e27202014-11-25 17:07:52 -0800451 * Variant that will try to locate deserializer for current type, but without
452 * performing any contextualization (unlike {@link #findContextualValueDeserializer})
453 * or checking for need to create a {@link TypeDeserializer} (unlike
454 * {@link #findRootValueDeserializer(JavaType)}.
455 * This method is usually called from within {@link ResolvableDeserializer#resolve},
456 * and expectation is that caller then calls either
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800457 * {@link #handlePrimaryContextualization(JsonDeserializer, BeanProperty, JavaType)} or
458 * {@link #handleSecondaryContextualization(JsonDeserializer, BeanProperty, JavaType)} at a
Cowtowncodera2e27202014-11-25 17:07:52 -0800459 * later point, as necessary.
460 *
461 * @since 2.5
462 */
463 public final JsonDeserializer<Object> findNonContextualValueDeserializer(JavaType type)
464 throws JsonMappingException
465 {
466 return _cache.findValueDeserializer(this, _factory, type);
467 }
468
469 /**
Tatuc3a73d02012-01-31 12:45:49 -0800470 * Method for finding a deserializer for root-level value.
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800471 */
Tatuc3a73d02012-01-31 12:45:49 -0800472 @SuppressWarnings("unchecked")
Tatu Saloranta9b9d0432012-01-30 09:20:26 -0800473 public final JsonDeserializer<Object> findRootValueDeserializer(JavaType type)
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700474 throws JsonMappingException
Tatuc3a73d02012-01-31 12:45:49 -0800475 {
Tatu Saloranta060ce112012-02-01 22:18:09 -0800476 JsonDeserializer<Object> deser = _cache.findValueDeserializer(this,
477 _factory, type);
Tatuc3a73d02012-01-31 12:45:49 -0800478 if (deser == null) { // can this occur?
479 return null;
480 }
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800481 deser = (JsonDeserializer<Object>) handleSecondaryContextualization(deser, null, type);
Tatuc3a73d02012-01-31 12:45:49 -0800482 TypeDeserializer typeDeser = _factory.findTypeDeserializer(_config, type);
483 if (typeDeser != null) {
484 // important: contextualize to indicate this is for root value
485 typeDeser = typeDeser.forProperty(null);
486 return new TypeWrappedDeserializer(typeDeser, deser);
487 }
488 return deser;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800489 }
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800490
491 /**
492 * Convenience method, functionally same as:
493 *<pre>
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700494 * getDeserializerProvider().findKeyDeserializer(getConfig(), prop.getType(), prop);
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800495 *</pre>
496 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800497 public final KeyDeserializer findKeyDeserializer(JavaType keyType,
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700498 BeanProperty prop) throws JsonMappingException {
Tatu Saloranta060ce112012-02-01 22:18:09 -0800499 KeyDeserializer kd = _cache.findKeyDeserializer(this,
500 _factory, keyType);
Tatud0bb3152012-01-31 13:04:06 -0800501 // Second: contextualize?
502 if (kd instanceof ContextualKeyDeserializer) {
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700503 kd = ((ContextualKeyDeserializer) kd).createContextual(this, prop);
Tatud0bb3152012-01-31 13:04:06 -0800504 }
505 return kd;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800506 }
507
Tatub37ff332012-01-24 16:19:36 -0800508 /*
509 /**********************************************************
Tatu Saloranta34a8adf2012-02-08 22:07:36 -0800510 /* Public API, ObjectId handling
511 /**********************************************************
512 */
513
514 /**
515 * Method called to find and return entry corresponding to given
516 * Object Id: will add an entry if necessary, and never returns null
517 */
Pascal GĂ©linas184cae32014-02-05 17:35:56 -0500518 public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> generator, ObjectIdResolver resolver);
519
Pascal GĂ©linas096e02b2013-12-18 17:21:42 -0500520 /**
521 * Method called to ensure that every object id encounter during processing
522 * are resolved.
523 *
524 * @throws UnresolvedForwardReference
525 */
526 public abstract void checkUnresolvedObjectId()
527 throws UnresolvedForwardReference;
528
Tatu Salorantabf5e0fa2012-03-08 21:45:30 -0800529 /*
530 /**********************************************************
531 /* Public API, type handling
532 /**********************************************************
533 */
534
535 /**
536 * Convenience method, functionally equivalent to:
537 *<pre>
538 * getConfig().constructType(cls);
539 * </pre>
540 */
541 public final JavaType constructType(Class<?> cls) {
Tatu Saloranta816bbed2016-10-05 21:13:12 -0700542 return (cls == null) ? null : _config.constructType(cls);
Tatu Salorantabf5e0fa2012-03-08 21:45:30 -0800543 }
544
545 /**
Cowtowncodera5bd0a22015-06-25 15:27:07 -0700546 * Helper method that is to be used when resolving basic class name into
547 * Class instance, the reason being that it may be necessary to work around
548 * various ClassLoader limitations, as well as to handle primitive type
549 * signatures.
550 *
551 * @since 2.6
Tatu Salorantabf5e0fa2012-03-08 21:45:30 -0800552 */
553 public Class<?> findClass(String className) throws ClassNotFoundException
554 {
555 // By default, delegate to ClassUtil: can be overridden with custom handling
Cowtowncodera5bd0a22015-06-25 15:27:07 -0700556 return getTypeFactory().findClass(className);
Tatu Salorantabf5e0fa2012-03-08 21:45:30 -0800557 }
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800558
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800559 /*
560 /**********************************************************
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800561 /* Public API, helper object recycling
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800562 /**********************************************************
563 */
564
565 /**
566 * Method that can be used to get access to a reusable ObjectBuffer,
567 * useful for efficiently constructing Object arrays and Lists.
568 * Note that leased buffers should be returned once deserializer
569 * is done, to allow for reuse during same round of deserialization.
570 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800571 public final ObjectBuffer leaseObjectBuffer()
572 {
573 ObjectBuffer buf = _objectBuffer;
574 if (buf == null) {
575 buf = new ObjectBuffer();
576 } else {
577 _objectBuffer = null;
578 }
579 return buf;
580 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800581
582 /**
583 * Method to call to return object buffer previously leased with
584 * {@link #leaseObjectBuffer}.
585 *
586 * @param buf Returned object buffer
587 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800588 public final void returnObjectBuffer(ObjectBuffer buf)
589 {
590 /* Already have a reusable buffer? Let's retain bigger one
591 * (or if equal, favor newer one, shorter life-cycle)
592 */
593 if (_objectBuffer == null
594 || buf.initialCapacity() >= _objectBuffer.initialCapacity()) {
595 _objectBuffer = buf;
596 }
597 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800598
599 /**
600 * Method for accessing object useful for building arrays of
601 * primitive types (such as int[]).
602 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800603 public final ArrayBuilders getArrayBuilders()
604 {
605 if (_arrayBuilders == null) {
606 _arrayBuilders = new ArrayBuilders();
607 }
608 return _arrayBuilders;
609 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800610
611 /*
612 /**********************************************************
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700613 /* Extended API: handler instantiation
614 /**********************************************************
615 */
616
617 public abstract JsonDeserializer<Object> deserializerInstance(Annotated annotated,
618 Object deserDef)
619 throws JsonMappingException;
620
621 public abstract KeyDeserializer keyDeserializerInstance(Annotated annotated,
622 Object deserDef)
623 throws JsonMappingException;
624
625 /*
626 /**********************************************************
627 /* Extended API: resolving contextual deserializers; called
628 /* by structured deserializers for their value/component
629 /* deserializers
630 /**********************************************************
631 */
632
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700633 /**
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700634 * Method called for primary property deserializers (ones
Tatu Saloranta59fe29c2013-09-05 22:37:06 -0700635 * directly created to deserialize values of a POJO property),
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700636 * to handle details of resolving
637 * {@link ContextualDeserializer} with given property context.
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700638 *
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700639 * @param prop Property for which the given primary deserializer is used; never null.
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700640 *
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800641 * @since 2.5
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700642 */
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700643 public JsonDeserializer<?> handlePrimaryContextualization(JsonDeserializer<?> deser,
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800644 BeanProperty prop, JavaType type)
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700645 throws JsonMappingException
646 {
Cowtowncodera2e27202014-11-25 17:07:52 -0800647 if (deser instanceof ContextualDeserializer) {
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800648 _currentType = new LinkedNode<JavaType>(type, _currentType);
649 try {
650 deser = ((ContextualDeserializer) deser).createContextual(this, prop);
651 } finally {
652 _currentType = _currentType.next();
653 }
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700654 }
655 return deser;
656 }
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700657
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700658 /**
659 * Method called for secondary property deserializers (ones
660 * NOT directly created to deal with an annotatable POJO property,
661 * but instead created as a component -- such as value deserializers
662 * for structured types, or deserializers for root values)
663 * to handle details of resolving
664 * {@link ContextualDeserializer} with given property context.
Tatu Saloranta59fe29c2013-09-05 22:37:06 -0700665 * Given that these deserializers are not directly related to given property
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700666 * (or, in case of root value property, to any property), annotations
667 * accessible may or may not be relevant.
668 *
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700669 * @param prop Property for which deserializer is used, if any; null
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700670 * when deserializing root values
671 *
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800672 * @since 2.5
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700673 */
674 public JsonDeserializer<?> handleSecondaryContextualization(JsonDeserializer<?> deser,
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800675 BeanProperty prop, JavaType type)
676 throws JsonMappingException
677 {
678 if (deser instanceof ContextualDeserializer) {
679 _currentType = new LinkedNode<JavaType>(type, _currentType);
680 try {
681 deser = ((ContextualDeserializer) deser).createContextual(this, prop);
682 } finally {
683 _currentType = _currentType.next();
684 }
685 }
686 return deser;
687 }
688
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700689 /*
690 /**********************************************************
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800691 /* Parsing methods that may use reusable/-cyclable objects
692 /**********************************************************
693 */
694
695 /**
696 * Convenience method for parsing a Date from given String, using
697 * currently configured date format (accessed using
698 * {@link DeserializationConfig#getDateFormat()}).
699 *<p>
700 * Implementation will handle thread-safety issues related to
701 * date formats such that first time this method is called,
702 * date format is cloned, and cloned instance will be retained
703 * for use during this deserialization round.
704 */
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700705 public Date parseDate(String dateStr) throws IllegalArgumentException
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800706 {
707 try {
Tatu Salorantaef00ac62013-11-03 09:56:39 -0800708 DateFormat df = getDateFormat();
709 return df.parse(dateStr);
Tatu Salorantaaa512742012-02-22 22:51:33 -0800710 } catch (ParseException e) {
Tatu Saloranta8e9d4b22015-05-01 21:26:32 -0700711 throw new IllegalArgumentException(String.format(
Tatu Salorantaf6cf1812018-09-05 23:17:05 -0700712 "Failed to parse Date value '%s': %s", dateStr,
713 ClassUtil.exceptionMessage(e)));
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800714 }
715 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800716
717 /**
718 * Convenience method for constructing Calendar instance set
719 * to specified time, to be modified and used by caller.
720 */
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700721 public Calendar constructCalendar(Date d) {
722 // 08-Jan-2008, tatu: not optimal, but should work for the most part; let's revise as needed.
Tatu Salorantaaa512742012-02-22 22:51:33 -0800723 Calendar c = Calendar.getInstance(getTimeZone());
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800724 c.setTime(d);
725 return c;
726 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800727
728 /*
729 /**********************************************************
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700730 /* Convenience methods for reading parsed values
731 /**********************************************************
732 */
733
734 /**
735 * Convenience method that may be used by composite or container deserializers,
736 * for reading one-off values contained (for sequences, it is more efficient
737 * to actually fetch deserializer once for the whole collection).
738 *<p>
739 * NOTE: when deserializing values of properties contained in composite types,
740 * rather use {@link #readPropertyValue(JsonParser, BeanProperty, Class)};
741 * this method does not allow use of contextual annotations.
742 *
743 * @since 2.4
744 */
745 public <T> T readValue(JsonParser p, Class<T> type) throws IOException {
746 return readValue(p, getTypeFactory().constructType(type));
747 }
748
749 /**
750 * @since 2.4
751 */
752 @SuppressWarnings("unchecked")
753 public <T> T readValue(JsonParser p, JavaType type) throws IOException {
754 JsonDeserializer<Object> deser = findRootValueDeserializer(type);
755 if (deser == null) {
Tatu Salorantac1478ac2016-09-29 08:17:03 -0700756 reportBadDefinition(type,
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700757 "Could not find JsonDeserializer for type "+ClassUtil.getTypeDescription(type));
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700758 }
759 return (T) deser.deserialize(p, this);
760 }
761
762 /**
763 * Convenience method that may be used by composite or container deserializers,
764 * for reading one-off values for the composite type, taking into account
765 * annotations that the property (passed to this method -- usually property that
766 * has custom serializer that called this method) has.
767 *
768 * @since 2.4
769 */
770 public <T> T readPropertyValue(JsonParser p, BeanProperty prop, Class<T> type) throws IOException {
771 return readPropertyValue(p, prop, getTypeFactory().constructType(type));
772 }
773
774 /**
775 * @since 2.4
776 */
777 @SuppressWarnings("unchecked")
778 public <T> T readPropertyValue(JsonParser p, BeanProperty prop, JavaType type) throws IOException {
779 JsonDeserializer<Object> deser = findContextualValueDeserializer(type, prop);
780 if (deser == null) {
Tatu Salorantac1478ac2016-09-29 08:17:03 -0700781 return reportBadDefinition(type, String.format(
Tatu Saloranta851092c2016-05-21 20:08:40 -0700782 "Could not find JsonDeserializer for type %s (via property %s)",
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700783 ClassUtil.getTypeDescription(type), ClassUtil.nameOf(prop)));
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700784 }
785 return (T) deser.deserialize(p, this);
786 }
Tatu Saloranta5ae6e4b2015-10-05 21:49:01 -0700787
Tatu Saloranta7904f922019-09-11 15:03:50 -0700788 /**
789 * @since 2.10
790 */
791 public JsonNode readTree(JsonParser p) throws IOException {
792 JsonToken t = p.currentToken();
793 if (t == null) {
794 t = p.nextToken();
795 if (t == null) {
796 return getNodeFactory().missingNode();
797 }
798 }
799 if (t == JsonToken.VALUE_NULL) {
800 return getNodeFactory().nullNode();
801 }
802 return (JsonNode) findRootValueDeserializer(_config.constructType(JsonNode.class))
803 .deserialize(p, this);
804 }
805
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700806 /*
807 /**********************************************************
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700808 /* Methods for problem handling
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800809 /**********************************************************
810 */
811
812 /**
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700813 * Method that deserializers should call if they encounter an unrecognized
814 * property (and once that is not explicitly designed as ignorable), to
815 * inform possibly configured {@link DeserializationProblemHandler}s and
816 * let it handle the problem.
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800817 *
818 * @return True if there was a configured problem handler that was able to handle the
Tatu Saloranta0e3b3832012-01-22 22:08:20 -0800819 * problem
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800820 */
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700821 public boolean handleUnknownProperty(JsonParser p, JsonDeserializer<?> deser,
Tatu Saloranta060ce112012-02-01 22:18:09 -0800822 Object instanceOrClass, String propName)
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700823 throws IOException
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800824 {
825 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700826 while (h != null) {
827 // Can bail out if it's handled
828 if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) {
829 return true;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800830 }
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700831 h = h.next();
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800832 }
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700833 // Nope, not handled. Potentially that's a problem...
834 if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
835 p.skipChildren();
836 return true;
837 }
838 // Do we know properties that are expected instead?
839 Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames();
840 throw UnrecognizedPropertyException.from(_parser,
841 instanceOrClass, propName, propIds);
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800842 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800843
844 /**
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700845 * Method that deserializers should call if they encounter a String value
Oliver Kopp5e3bf082017-06-27 14:12:19 +0300846 * that cannot be converted to expected key of a {@link java.util.Map}
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700847 * valued property.
848 * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue}
849 * on configured handlers, if any, to allow for recovery; if recovery does not
850 * succeed, will throw {@link InvalidFormatException} with given message.
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700851 *
852 * @param keyClass Expected type for key
853 * @param keyValue String value from which to deserialize key
854 * @param msg Error message template caller wants to use if exception is to be thrown
855 * @param msgArgs Optional arguments to use for message, if any
856 *
857 * @return Key value to use
858 *
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700859 * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700860 *
861 * @since 2.8
862 */
863 public Object handleWeirdKey(Class<?> keyClass, String keyValue,
864 String msg, Object... msgArgs)
865 throws IOException
866 {
867 // but if not handled, just throw exception
Tatu Saloranta79124862016-10-19 22:13:29 -0700868 msg = _format(msg, msgArgs);
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700869 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700870 while (h != null) {
871 // Can bail out if it's handled
872 Object key = h.value().handleWeirdKey(this, keyClass, keyValue, msg);
Tatu Saloranta2d318f62016-05-10 21:58:00 -0700873 if (key != DeserializationProblemHandler.NOT_HANDLED) {
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700874 // Sanity check for broken handlers, otherwise nasty to debug:
875 if ((key == null) || keyClass.isInstance(key)) {
876 return key;
877 }
878 throw weirdStringException(keyValue, keyClass, String.format(
879 "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700880 ClassUtil.getClassDescription(keyClass),
881 ClassUtil.getClassDescription(key)
882 ));
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700883 }
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700884 h = h.next();
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700885 }
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700886 throw weirdKeyException(keyClass, keyValue, msg);
887 }
888
889 /**
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -0700890 * Method that deserializers should call if they encounter a String value
Oliver Kopp5e3bf082017-06-27 14:12:19 +0300891 * that cannot be converted to target property type, in cases where some
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -0700892 * String values could be acceptable (either with different settings,
893 * or different value).
894 * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdStringValue}
895 * on configured handlers, if any, to allow for recovery; if recovery does not
896 * succeed, will throw {@link InvalidFormatException} with given message.
897 *
898 * @param targetClass Type of property into which incoming number should be converted
899 * @param value String value from which to deserialize property value
900 * @param msg Error message template caller wants to use if exception is to be thrown
901 * @param msgArgs Optional arguments to use for message, if any
902 *
903 * @return Property value to use
904 *
905 * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
906 *
907 * @since 2.8
908 */
909 public Object handleWeirdStringValue(Class<?> targetClass, String value,
910 String msg, Object... msgArgs)
911 throws IOException
912 {
913 // but if not handled, just throw exception
Tatu Saloranta79124862016-10-19 22:13:29 -0700914 msg = _format(msg, msgArgs);
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -0700915 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
916 while (h != null) {
917 // Can bail out if it's handled
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700918 Object instance = h.value().handleWeirdStringValue(this, targetClass, value, msg);
919 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
920 // Sanity check for broken handlers, otherwise nasty to debug:
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -0700921 if (_isCompatible(targetClass, instance)) {
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700922 return instance;
923 }
924 throw weirdStringException(value, targetClass, String.format(
925 "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700926 ClassUtil.getClassDescription(targetClass),
927 ClassUtil.getClassDescription(instance)
928 ));
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -0700929 }
930 h = h.next();
931 }
932 throw weirdStringException(value, targetClass, msg);
933 }
934
935 /**
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700936 * Method that deserializers should call if they encounter a numeric value
Oliver Kopp5e3bf082017-06-27 14:12:19 +0300937 * that cannot be converted to target property type, in cases where some
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700938 * numeric values could be acceptable (either with different settings,
939 * or different numeric value).
940 * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue}
941 * on configured handlers, if any, to allow for recovery; if recovery does not
942 * succeed, will throw {@link InvalidFormatException} with given message.
943 *
944 * @param targetClass Type of property into which incoming number should be converted
945 * @param value Number value from which to deserialize property value
946 * @param msg Error message template caller wants to use if exception is to be thrown
947 * @param msgArgs Optional arguments to use for message, if any
948 *
949 * @return Property value to use
950 *
951 * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
952 *
953 * @since 2.8
954 */
955 public Object handleWeirdNumberValue(Class<?> targetClass, Number value,
956 String msg, Object... msgArgs)
957 throws IOException
958 {
Tatu Saloranta79124862016-10-19 22:13:29 -0700959 msg = _format(msg, msgArgs);
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700960 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
961 while (h != null) {
962 // Can bail out if it's handled
963 Object key = h.value().handleWeirdNumberValue(this, targetClass, value, msg);
964 if (key != DeserializationProblemHandler.NOT_HANDLED) {
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700965 // Sanity check for broken handlers, otherwise nasty to debug:
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -0700966 if (_isCompatible(targetClass, key)) {
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700967 return key;
968 }
Tatu Saloranta23a610d2017-07-26 16:57:29 -0700969 throw weirdNumberException(value, targetClass, _format(
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700970 "DeserializationProblemHandler.handleWeirdNumberValue() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700971 ClassUtil.getClassDescription(targetClass),
972 ClassUtil.getClassDescription(key)
973 ));
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700974 }
975 h = h.next();
976 }
977 throw weirdNumberException(value, targetClass, msg);
978 }
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -0700979
Tatu Saloranta23a610d2017-07-26 16:57:29 -0700980 public Object handleWeirdNativeValue(JavaType targetType, Object badValue,
981 JsonParser p)
982 throws IOException
983 {
984 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
985 final Class<?> raw = targetType.getRawClass();
986 for (; h != null; h = h.next()) {
987 // Can bail out if it's handled
988 Object goodValue = h.value().handleWeirdNativeValue(this, targetType, badValue, p);
989 if (goodValue != DeserializationProblemHandler.NOT_HANDLED) {
990 // Sanity check for broken handlers, otherwise nasty to debug:
991 if ((goodValue == null) || raw.isInstance(goodValue)) {
992 return goodValue;
993 }
994 throw JsonMappingException.from(p, _format(
995"DeserializationProblemHandler.handleWeirdNativeValue() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700996 ClassUtil.getClassDescription(targetType),
997 ClassUtil.getClassDescription(goodValue)
998 ));
Tatu Saloranta23a610d2017-07-26 16:57:29 -0700999 }
1000 }
1001 throw weirdNativeValueException(badValue, raw);
1002 }
1003
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001004 /**
Tatu Saloranta68245442016-05-21 18:08:41 -07001005 * Method that deserializers should call if they fail to instantiate value
1006 * due to lack of viable instantiator (usually creator, that is, constructor
1007 * or static factory method). Method should be called at point where value
1008 * has not been decoded, so that handler has a chance to handle decoding
1009 * using alternate mechanism, and handle underlying content (possibly by
1010 * just skipping it) to keep input state valid
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001011 *
Tatu Saloranta68245442016-05-21 18:08:41 -07001012 * @param instClass Type that was to be instantiated
Tatu Salorantaed416862016-10-16 13:42:12 -07001013 * @param valueInst (optional) Value instantiator to be used, if any; null if type does not
1014 * use one for instantiation (custom deserialiers don't; standard POJO deserializer does)
Tatu Saloranta68245442016-05-21 18:08:41 -07001015 * @param p Parser that points to the JSON value to decode
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001016 *
Tatu Saloranta68245442016-05-21 18:08:41 -07001017 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001018 *
Tatu Salorantaed416862016-10-16 13:42:12 -07001019 * @since 2.9 (2.8 had alternate that did not take <code>ValueInstantiator</code>)
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001020 */
Tatu Salorantaed416862016-10-16 13:42:12 -07001021 @SuppressWarnings("resource")
1022 public Object handleMissingInstantiator(Class<?> instClass, ValueInstantiator valueInst,
1023 JsonParser p, String msg, Object... msgArgs)
Tatu Saloranta68245442016-05-21 18:08:41 -07001024 throws IOException
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001025 {
Tatu Salorantaed416862016-10-16 13:42:12 -07001026 if (p == null) {
1027 p = getParser();
1028 }
Tatu Saloranta79124862016-10-19 22:13:29 -07001029 msg = _format(msg, msgArgs);
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001030 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1031 while (h != null) {
1032 // Can bail out if it's handled
Tatu Saloranta68245442016-05-21 18:08:41 -07001033 Object instance = h.value().handleMissingInstantiator(this,
Tatu Salorantaed416862016-10-16 13:42:12 -07001034 instClass, valueInst, p, msg);
Tatu Saloranta68245442016-05-21 18:08:41 -07001035 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
1036 // Sanity check for broken handlers, otherwise nasty to debug:
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -07001037 if (_isCompatible(instClass, instance)) {
Tatu Saloranta68245442016-05-21 18:08:41 -07001038 return instance;
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001039 }
Tatu Saloranta816bbed2016-10-05 21:13:12 -07001040 reportBadDefinition(constructType(instClass), String.format(
1041"DeserializationProblemHandler.handleMissingInstantiator() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001042 ClassUtil.getClassDescription(instClass),
1043 ClassUtil.getClassDescription((instance)
1044 )));
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001045 }
1046 h = h.next();
1047 }
Tatu Salorantaed416862016-10-16 13:42:12 -07001048
1049 // 16-Oct-2016, tatu: This is either a definition problem (if no applicable creator
Tatu Saloranta581ba1f2017-01-25 21:55:11 -08001050 // exists), or input mismatch problem (otherwise) since none of existing creators
Tatu Salorantaed416862016-10-16 13:42:12 -07001051 // match with token.
1052 if ((valueInst != null) && !valueInst.canInstantiate()) {
Oliver Kopp68476802017-06-27 22:26:41 +03001053 msg = String.format("Cannot construct instance of %s (no Creators, like default construct, exist): %s",
Tatu Saloranta267abe12016-11-25 18:14:20 -08001054 ClassUtil.nameOf(instClass), msg);
Tatu Salorantaed416862016-10-16 13:42:12 -07001055 return reportBadDefinition(constructType(instClass), msg);
1056 }
Oliver Kopp68476802017-06-27 22:26:41 +03001057 msg = String.format("Cannot construct instance of %s (although at least one Creator exists): %s",
Tatu Saloranta267abe12016-11-25 18:14:20 -08001058 ClassUtil.nameOf(instClass), msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001059 return reportInputMismatch(instClass, msg);
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001060 }
1061
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001062 /**
1063 * Method that deserializers should call if they fail to instantiate value
1064 * due to an exception that was thrown by constructor (or other mechanism used
1065 * to create instances).
1066 * Default implementation will try to call {@link DeserializationProblemHandler#handleInstantiationProblem}
1067 * on configured handlers, if any, to allow for recovery; if recovery does not
1068 * succeed, will throw exception constructed with {@link #instantiationException}.
1069 *
1070 * @param instClass Type that was to be instantiated
1071 * @param argument (optional) Argument that was passed to constructor or equivalent
1072 * instantiator; often a {@link java.lang.String}.
1073 * @param t Exception that caused failure
1074 *
1075 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1076 *
1077 * @since 2.8
1078 */
1079 public Object handleInstantiationProblem(Class<?> instClass, Object argument,
1080 Throwable t)
1081 throws IOException
1082 {
1083 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1084 while (h != null) {
1085 // Can bail out if it's handled
Tatu Salorantad01e3ab2016-05-19 09:31:38 -07001086 Object instance = h.value().handleInstantiationProblem(this, instClass, argument, t);
1087 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
1088 // Sanity check for broken handlers, otherwise nasty to debug:
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -07001089 if (_isCompatible(instClass, instance)) {
Tatu Salorantad01e3ab2016-05-19 09:31:38 -07001090 return instance;
1091 }
Tatu Saloranta816bbed2016-10-05 21:13:12 -07001092 reportBadDefinition(constructType(instClass), String.format(
1093"DeserializationProblemHandler.handleInstantiationProblem() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001094 ClassUtil.getClassDescription(instClass),
1095 ClassUtil.classNameOf(instance)
1096 ));
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001097 }
1098 h = h.next();
1099 }
1100 // 18-May-2016, tatu: Only wrap if not already a valid type to throw
Tatu Saloranta78c72292016-11-07 20:37:45 -08001101 ClassUtil.throwIfIOE(t);
Tatu Salorantae3ec9dc2019-09-11 16:33:32 -07001102 // [databind#2164]: but see if wrapping is desired
1103 if (!isEnabled(DeserializationFeature.WRAP_EXCEPTIONS)) {
1104 ClassUtil.throwIfRTE(t);
1105 }
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001106 throw instantiationException(instClass, t);
1107 }
1108
Tatu Saloranta68245442016-05-21 18:08:41 -07001109 /**
Tatu Saloranta851092c2016-05-21 20:08:40 -07001110 * Method that deserializers should call if the first token of the value to
1111 * deserialize is of unexpected type (that is, type of token that deserializer
Oliver Kopp5e3bf082017-06-27 14:12:19 +03001112 * cannot handle). This could occur, for example, if a Number deserializer
Tatu Saloranta851092c2016-05-21 20:08:40 -07001113 * encounter {@link JsonToken#START_ARRAY} instead of
1114 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1115 *
1116 * @param instClass Type that was to be instantiated
1117 * @param p Parser that points to the JSON value to decode
1118 *
1119 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1120 *
1121 * @since 2.8
1122 */
1123 public Object handleUnexpectedToken(Class<?> instClass, JsonParser p)
1124 throws IOException
1125 {
Tatu Saloranta2599caf2019-09-15 16:17:48 -07001126 return handleUnexpectedToken(constructType(instClass), p.getCurrentToken(), p, null);
Tatu Saloranta851092c2016-05-21 20:08:40 -07001127 }
Tatu Saloranta43fbd712016-11-09 21:43:27 -08001128
Tatu Saloranta851092c2016-05-21 20:08:40 -07001129 /**
1130 * Method that deserializers should call if the first token of the value to
1131 * deserialize is of unexpected type (that is, type of token that deserializer
Oliver Kopp5e3bf082017-06-27 14:12:19 +03001132 * cannot handle). This could occur, for example, if a Number deserializer
Tatu Saloranta851092c2016-05-21 20:08:40 -07001133 * encounter {@link JsonToken#START_ARRAY} instead of
1134 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1135 *
1136 * @param instClass Type that was to be instantiated
Tatu Saloranta2a877182016-10-15 18:18:22 -07001137 * @param t Token encountered that does match expected
Tatu Saloranta851092c2016-05-21 20:08:40 -07001138 * @param p Parser that points to the JSON value to decode
1139 *
1140 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1141 *
1142 * @since 2.8
1143 */
1144 public Object handleUnexpectedToken(Class<?> instClass, JsonToken t,
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001145 JsonParser p, String msg, Object... msgArgs)
Tatu Saloranta851092c2016-05-21 20:08:40 -07001146 throws IOException
1147 {
Semyon Levin28e775f2019-09-16 02:01:56 +03001148 return handleUnexpectedToken(constructType(instClass), t, p, msg, msgArgs);
1149 }
1150
1151 /**
1152 * Method that deserializers should call if the first token of the value to
1153 * deserialize is of unexpected type (that is, type of token that deserializer
1154 * cannot handle). This could occur, for example, if a Number deserializer
1155 * encounter {@link JsonToken#START_ARRAY} instead of
1156 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1157 *
1158 * @param targetType Type that was to be instantiated
1159 * @param p Parser that points to the JSON value to decode
1160 *
1161 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1162 *
1163 * @since 2.10
1164 */
1165 public Object handleUnexpectedToken(JavaType targetType, JsonParser p)
1166 throws IOException
1167 {
1168 return handleUnexpectedToken(targetType, p.getCurrentToken(), p, null);
1169 }
1170
1171 /**
1172 * Method that deserializers should call if the first token of the value to
1173 * deserialize is of unexpected type (that is, type of token that deserializer
1174 * cannot handle). This could occur, for example, if a Number deserializer
1175 * encounter {@link JsonToken#START_ARRAY} instead of
1176 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1177 *
1178 * @param targetType Type that was to be instantiated
1179 * @param t Token encountered that does match expected
1180 * @param p Parser that points to the JSON value to decode
1181 *
1182 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1183 *
1184 * @since 2.10
1185 */
1186 public Object handleUnexpectedToken(JavaType targetType, JsonToken t,
1187 JsonParser p, String msg, Object... msgArgs)
1188 throws IOException
1189 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001190 msg = _format(msg, msgArgs);
Tatu Saloranta851092c2016-05-21 20:08:40 -07001191 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1192 while (h != null) {
1193 Object instance = h.value().handleUnexpectedToken(this,
Semyon Levin28e775f2019-09-16 02:01:56 +03001194 targetType, t, p, msg);
Tatu Saloranta851092c2016-05-21 20:08:40 -07001195 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
Semyon Levin28e775f2019-09-16 02:01:56 +03001196 if (_isCompatible(targetType.getRawClass(), instance)) {
Tatu Saloranta851092c2016-05-21 20:08:40 -07001197 return instance;
1198 }
Semyon Levin28e775f2019-09-16 02:01:56 +03001199 reportBadDefinition(targetType, String.format(
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001200 "DeserializationProblemHandler.handleUnexpectedToken() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001201 ClassUtil.getClassDescription(targetType),
1202 ClassUtil.classNameOf(instance)
1203 ));
Tatu Saloranta851092c2016-05-21 20:08:40 -07001204 }
1205 h = h.next();
1206 }
Tatu Saloranta851092c2016-05-21 20:08:40 -07001207 if (msg == null) {
Tatu Saloranta73359ae2016-06-06 08:44:54 -07001208 if (t == null) {
1209 msg = String.format("Unexpected end-of-input when binding data into %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001210 ClassUtil.getTypeDescription(targetType));
Tatu Saloranta73359ae2016-06-06 08:44:54 -07001211 } else {
Oliver Kopp68476802017-06-27 22:26:41 +03001212 msg = String.format("Cannot deserialize instance of %s out of %s token",
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001213 ClassUtil.getTypeDescription(targetType), t);
Tatu Saloranta73359ae2016-06-06 08:44:54 -07001214 }
Tatu Saloranta851092c2016-05-21 20:08:40 -07001215 }
Semyon Levin28e775f2019-09-16 02:01:56 +03001216 reportInputMismatch(targetType, msg);
Tatu Salorantaacc533a2016-05-22 21:47:18 -07001217 return null; // never gets here
Tatu Saloranta851092c2016-05-21 20:08:40 -07001218 }
1219
1220 /**
Tatu Saloranta68245442016-05-21 18:08:41 -07001221 * Method that deserializers should call if they encounter a type id
Oliver Kopp5e3bf082017-06-27 14:12:19 +03001222 * (for polymorphic deserialization) that cannot be resolved to an
Tatu Saloranta68245442016-05-21 18:08:41 -07001223 * actual type; usually since there is no mapping defined.
1224 * Default implementation will try to call {@link DeserializationProblemHandler#handleUnknownTypeId}
1225 * on configured handlers, if any, to allow for recovery; if recovery does not
Tatu Saloranta3ee81a62017-05-02 10:01:48 -07001226 * succeed, will throw exception constructed with {@link #invalidTypeIdException}.
Tatu Saloranta68245442016-05-21 18:08:41 -07001227 *
1228 * @param baseType Base type from which resolution starts
1229 * @param id Type id that could not be converted
1230 * @param extraDesc Additional problem description to add to default exception message,
1231 * if resolution fails.
1232 *
1233 * @return {@link JavaType} that id resolves to
1234 *
Oliver Kopp5e3bf082017-06-27 14:12:19 +03001235 * @throws IOException To indicate unrecoverable problem, if resolution cannot
Tatu Saloranta68245442016-05-21 18:08:41 -07001236 * be made to work
1237 *
1238 * @since 2.8
1239 */
1240 public JavaType handleUnknownTypeId(JavaType baseType, String id,
Tatu Salorantad6230fd2016-05-30 21:11:19 -07001241 TypeIdResolver idResolver, String extraDesc) throws IOException
Tatu Saloranta68245442016-05-21 18:08:41 -07001242 {
1243 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1244 while (h != null) {
1245 // Can bail out if it's handled
Tatu Salorantad6230fd2016-05-30 21:11:19 -07001246 JavaType type = h.value().handleUnknownTypeId(this, baseType, id, idResolver, extraDesc);
Tatu Saloranta68245442016-05-21 18:08:41 -07001247 if (type != null) {
1248 if (type.hasRawClass(Void.class)) {
1249 return null;
1250 }
1251 // But ensure there's type compatibility
1252 if (type.isTypeOrSubTypeOf(baseType.getRawClass())) {
1253 return type;
1254 }
Tatu Saloranta52238562017-04-28 10:52:23 -07001255 throw invalidTypeIdException(baseType, id,
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001256 "problem handler tried to resolve into non-subtype: "+
1257 ClassUtil.getTypeDescription(type));
Tatu Saloranta68245442016-05-21 18:08:41 -07001258 }
1259 h = h.next();
1260 }
Tatu Saloranta811ec172016-05-24 23:39:04 -07001261 // 24-May-2016, tatu: Actually we may still not want to fail quite yet
1262 if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
1263 return null;
1264 }
Tatu Saloranta52238562017-04-28 10:52:23 -07001265 throw invalidTypeIdException(baseType, id, extraDesc);
Tatu Saloranta68245442016-05-21 18:08:41 -07001266 }
1267
Tatu Saloranta5b8f0d92017-03-09 10:18:47 -08001268 /**
1269 * @since 2.9
1270 */
1271 public JavaType handleMissingTypeId(JavaType baseType,
1272 TypeIdResolver idResolver, String extraDesc) throws IOException
1273 {
1274 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1275 while (h != null) {
1276 // Can bail out if it's handled
1277 JavaType type = h.value().handleMissingTypeId(this, baseType, idResolver, extraDesc);
1278 if (type != null) {
1279 if (type.hasRawClass(Void.class)) {
1280 return null;
1281 }
1282 // But ensure there's type compatibility
1283 if (type.isTypeOrSubTypeOf(baseType.getRawClass())) {
1284 return type;
1285 }
Tatu Saloranta52238562017-04-28 10:52:23 -07001286 throw invalidTypeIdException(baseType, null,
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001287 "problem handler tried to resolve into non-subtype: "+
1288 ClassUtil.getTypeDescription(type));
Tatu Saloranta5b8f0d92017-03-09 10:18:47 -08001289 }
1290 h = h.next();
1291 }
1292 // 09-Mar-2017, tatu: We may want to consider yet another feature at some
1293 // point to allow returning `null`... but that seems bit risky for now
1294// if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
1295// return null;
1296// }
1297 throw missingTypeIdException(baseType, extraDesc);
1298 }
1299
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -07001300 /**
Tatu Saloranta9051c792019-08-20 20:12:34 -07001301 * Method that deserializer may call if it is called to do an update ("merge")
1302 * but deserializer operates on a non-mergeable type. Although this should
1303 * usually be caught earlier, sometimes it may only be caught during operation
1304 * and if so this is the method to call.
1305 * Note that if {@link MapperFeature#IGNORE_MERGE_FOR_UNMERGEABLE} is enabled,
1306 * this method will simply return null; otherwise {@link InvalidDefinitionException}
1307 * will be thrown.
1308 *
1309 * @since 2.10
1310 */
1311 public void handleBadMerge(JsonDeserializer<?> deser) throws JsonMappingException
1312 {
1313 if (!isEnabled(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)) {
1314 JavaType type = constructType(deser.handledType());
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001315 String msg = String.format("Invalid configuration: values of type %s cannot be merged",
1316 ClassUtil.getTypeDescription(type));
Tatu Saloranta9051c792019-08-20 20:12:34 -07001317 throw InvalidDefinitionException.from(getParser(), msg, type);
1318 }
1319 }
1320
1321 /**
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -07001322 * @since 2.9.2
1323 */
1324 protected boolean _isCompatible(Class<?> target, Object value)
1325 {
1326 if ((value == null) || target.isInstance(value)) {
1327 return true;
1328 }
1329 // [databind#1767]: Make sure to allow wrappers for primitive fields
1330 return target.isPrimitive()
1331 && ClassUtil.wrapperType(target).isInstance(value);
1332 }
1333
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001334 /*
1335 /**********************************************************
Tatu Saloranta68245442016-05-21 18:08:41 -07001336 /* Methods for problem reporting, in cases where recovery
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001337 /* is not considered possible: input problem
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001338 /**********************************************************
1339 */
1340
1341 /**
Tatu Saloranta68245442016-05-21 18:08:41 -07001342 * Method for deserializers to call
1343 * when the token encountered was of type different than what <b>should</b>
1344 * be seen at that position, usually within a sequence of expected tokens.
1345 * Note that this method will throw a {@link JsonMappingException} and no
1346 * recovery is attempted (via {@link DeserializationProblemHandler}, as
1347 * problem is considered to be difficult to recover from, in general.
1348 *
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001349 * @since 2.9
Tatu Saloranta68245442016-05-21 18:08:41 -07001350 */
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001351 public void reportWrongTokenException(JsonDeserializer<?> deser,
1352 JsonToken expToken, String msg, Object... msgArgs)
1353 throws JsonMappingException
1354 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001355 msg = _format(msg, msgArgs);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001356 throw wrongTokenException(getParser(), deser.handledType(), expToken, msg);
1357 }
1358
1359 /**
1360 * Method for deserializers to call
1361 * when the token encountered was of type different than what <b>should</b>
1362 * be seen at that position, usually within a sequence of expected tokens.
1363 * Note that this method will throw a {@link JsonMappingException} and no
1364 * recovery is attempted (via {@link DeserializationProblemHandler}, as
1365 * problem is considered to be difficult to recover from, in general.
1366 *
1367 * @since 2.9
1368 */
1369 public void reportWrongTokenException(JavaType targetType,
1370 JsonToken expToken, String msg, Object... msgArgs)
1371 throws JsonMappingException
1372 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001373 msg = _format(msg, msgArgs);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001374 throw wrongTokenException(getParser(), targetType, expToken, msg);
1375 }
1376
1377 /**
1378 * Method for deserializers to call
1379 * when the token encountered was of type different than what <b>should</b>
1380 * be seen at that position, usually within a sequence of expected tokens.
1381 * Note that this method will throw a {@link JsonMappingException} and no
1382 * recovery is attempted (via {@link DeserializationProblemHandler}, as
1383 * problem is considered to be difficult to recover from, in general.
1384 *
1385 * @since 2.9
1386 */
1387 public void reportWrongTokenException(Class<?> targetType,
1388 JsonToken expToken, String msg, Object... msgArgs)
1389 throws JsonMappingException
1390 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001391 msg = _format(msg, msgArgs);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001392 throw wrongTokenException(getParser(), targetType, expToken, msg);
1393 }
Tatu Saloranta9d1fb752016-06-07 22:47:04 -07001394
1395 /**
1396 * @since 2.8
1397 */
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001398 public <T> T reportUnresolvedObjectId(ObjectIdReader oidReader, Object bean)
Tatu Saloranta9d1fb752016-06-07 22:47:04 -07001399 throws JsonMappingException
1400 {
1401 String msg = String.format("No Object Id found for an instance of %s, to assign to property '%s'",
Tatu Saloranta267abe12016-11-25 18:14:20 -08001402 ClassUtil.classNameOf(bean), oidReader.propertyName);
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001403 return reportInputMismatch(oidReader.idProperty, msg);
Tatu Saloranta9d1fb752016-06-07 22:47:04 -07001404 }
1405
Tatu Salorantabb06aa02016-09-08 22:38:23 -07001406 /**
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001407 * Helper method used to indicate a problem with input in cases where more
1408 * specific <code>reportXxx()</code> method was not available.
1409 *
1410 * @since 2.9
1411 */
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001412 public <T> T reportInputMismatch(JsonDeserializer<?> src,
1413 String msg, Object... msgArgs) throws JsonMappingException
1414 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001415 msg = _format(msg, msgArgs);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001416 throw MismatchedInputException.from(getParser(), src.handledType(), msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001417 }
1418
1419 /**
1420 * Helper method used to indicate a problem with input in cases where more
1421 * specific <code>reportXxx()</code> method was not available.
1422 *
1423 * @since 2.9
1424 */
1425 public <T> T reportInputMismatch(Class<?> targetType,
1426 String msg, Object... msgArgs) throws JsonMappingException
1427 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001428 msg = _format(msg, msgArgs);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001429 throw MismatchedInputException.from(getParser(), targetType, msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001430 }
1431
1432 /**
1433 * Helper method used to indicate a problem with input in cases where more
1434 * specific <code>reportXxx()</code> method was not available.
1435 *
1436 * @since 2.9
1437 */
1438 public <T> T reportInputMismatch(JavaType targetType,
1439 String msg, Object... msgArgs) throws JsonMappingException
1440 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001441 msg = _format(msg, msgArgs);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001442 throw MismatchedInputException.from(getParser(), targetType, msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001443 }
Tatu Salorantab8f60292016-10-25 22:50:06 -07001444
Tatu Salorantab3e41942019-09-11 14:18:02 -07001445 /**
1446 * Helper method used to indicate a problem with input in cases where more
1447 * specific <code>reportXxx()</code> method was not available.
1448 *
1449 * @since 2.9
1450 */
1451 public <T> T reportInputMismatch(BeanProperty prop,
1452 String msg, Object... msgArgs) throws JsonMappingException
1453 {
1454 msg = _format(msg, msgArgs);
1455 JavaType type = (prop == null) ? null : prop.getType();
1456 final MismatchedInputException e = MismatchedInputException.from(getParser(), type, msg);
1457 // [databind#2357]: Include property name, if we have it
1458 if (prop != null) {
1459 AnnotatedMember member = prop.getMember();
1460 if (member != null) {
1461 e.prependPath(member.getDeclaringClass(), prop.getName());
1462 }
1463 }
1464 throw e;
1465 }
1466
1467 /**
1468 * Helper method used to indicate a problem with input in cases where more
1469 * specific <code>reportXxx()</code> method was not available.
1470 *
1471 * @since 2.10
1472 */
1473 public <T> T reportPropertyInputMismatch(Class<?> targetType, String propertyName,
1474 String msg, Object... msgArgs) throws JsonMappingException
1475 {
1476 msg = _format(msg, msgArgs);
1477 MismatchedInputException e = MismatchedInputException.from(getParser(), targetType, msg);
1478 if (propertyName != null) {
1479 e.prependPath(targetType, propertyName);
1480 }
1481 throw e;
1482 }
1483
1484 /**
1485 * Helper method used to indicate a problem with input in cases where more
1486 * specific <code>reportXxx()</code> method was not available.
1487 *
1488 * @since 2.10
1489 */
1490 public <T> T reportPropertyInputMismatch(JavaType targetType, String propertyName,
1491 String msg, Object... msgArgs) throws JsonMappingException
1492 {
1493 return reportPropertyInputMismatch(targetType.getRawClass(), propertyName, msg, msgArgs);
1494 }
1495
Tatu Saloranta8f9226b2017-07-18 17:18:08 -07001496 public <T> T reportTrailingTokens(Class<?> targetType,
1497 JsonParser p, JsonToken trailingToken) throws JsonMappingException
1498 {
1499 throw MismatchedInputException.from(p, targetType, String.format(
1500"Trailing token (of type %s) found after value (bound as %s): not allowed as per `DeserializationFeature.FAIL_ON_TRAILING_TOKENS`",
1501trailingToken, ClassUtil.nameOf(targetType)
1502 ));
1503 }
1504
Tatu Salorantab8f60292016-10-25 22:50:06 -07001505 @Deprecated // since 2.9
1506 public void reportWrongTokenException(JsonParser p,
1507 JsonToken expToken, String msg, Object... msgArgs)
1508 throws JsonMappingException
1509 {
1510 msg = _format(msg, msgArgs);
1511 throw wrongTokenException(p, expToken, msg);
1512 }
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001513
Tatu Salorantab8f60292016-10-25 22:50:06 -07001514 /**
1515 * Helper method for reporting a problem with unhandled unknown property.
1516 *
1517 * @param instanceOrClass Either value being populated (if one has been
1518 * instantiated), or Class that indicates type that would be (or
1519 * have been) instantiated
1520 * @param deser Deserializer that had the problem, if called by deserializer
1521 * (or on behalf of one)
1522 *
1523 * @deprecated Since 2.8 call {@link #handleUnknownProperty} instead
1524 */
1525 @Deprecated
1526 public void reportUnknownProperty(Object instanceOrClass, String fieldName,
1527 JsonDeserializer<?> deser)
1528 throws JsonMappingException
1529 {
1530 if (isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
1531 // Do we know properties that are expected instead?
1532 Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames();
1533 throw UnrecognizedPropertyException.from(_parser,
1534 instanceOrClass, fieldName, propIds);
1535 }
1536 }
1537
1538 /**
1539 * @since 2.8
1540 *
1541 * @deprecated Since 2.9: not clear this ever occurs
1542 */
1543 @Deprecated // since 2.9
1544 public void reportMissingContent(String msg, Object... msgArgs) throws JsonMappingException {
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001545 throw MismatchedInputException.from(getParser(), (JavaType) null, "No content to map due to end-of-input");
Tatu Salorantab8f60292016-10-25 22:50:06 -07001546 }
1547
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001548 /*
1549 /**********************************************************
1550 /* Methods for problem reporting, in cases where recovery
1551 /* is not considered possible: POJO definition problems
1552 /**********************************************************
1553 */
1554
1555 /**
Tatu Salorantabb06aa02016-09-08 22:38:23 -07001556 * Helper method called to indicate problem in POJO (serialization) definitions or settings
1557 * regarding specific Java type, unrelated to actual JSON content to map.
1558 * Default behavior is to construct and throw a {@link JsonMappingException}.
1559 *
1560 * @since 2.9
1561 */
1562 public <T> T reportBadTypeDefinition(BeanDescription bean,
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001563 String msg, Object... msgArgs) throws JsonMappingException {
1564 msg = _format(msg, msgArgs);
Tatu Salorantae0889202017-03-30 15:43:20 -07001565 String beanDesc = ClassUtil.nameOf(bean.getBeanClass());
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001566 msg = String.format("Invalid type definition for type %s: %s", beanDesc, msg);
1567 throw InvalidDefinitionException.from(_parser, msg, bean, null);
Tatu Salorantabb06aa02016-09-08 22:38:23 -07001568 }
1569
1570 /**
1571 * Helper method called to indicate problem in POJO (serialization) definitions or settings
1572 * regarding specific property (of a type), unrelated to actual JSON content to map.
1573 * Default behavior is to construct and throw a {@link JsonMappingException}.
1574 *
1575 * @since 2.9
1576 */
1577 public <T> T reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop,
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001578 String msg, Object... msgArgs) throws JsonMappingException {
1579 msg = _format(msg, msgArgs);
Tatu Saloranta43fbd712016-11-09 21:43:27 -08001580 String propName = ClassUtil.nameOf(prop);
Tatu Salorantae0889202017-03-30 15:43:20 -07001581 String beanDesc = ClassUtil.nameOf(bean.getBeanClass());
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001582 msg = String.format("Invalid definition for property %s (of type %s): %s",
1583 propName, beanDesc, msg);
1584 throw InvalidDefinitionException.from(_parser, msg, bean, prop);
Tatu Salorantabb06aa02016-09-08 22:38:23 -07001585 }
1586
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001587 @Override
1588 public <T> T reportBadDefinition(JavaType type, String msg) throws JsonMappingException {
1589 throw InvalidDefinitionException.from(_parser, msg, type);
Tatu Saloranta851092c2016-05-21 20:08:40 -07001590 }
1591
Tatu Salorantab8f60292016-10-25 22:50:06 -07001592 /**
Tatu Saloranta9051c792019-08-20 20:12:34 -07001593 * @deprecated Since 2.10 use {@link #handleBadMerge} instead
Tatu Salorantab8f60292016-10-25 22:50:06 -07001594 */
Tatu Saloranta9051c792019-08-20 20:12:34 -07001595 @Deprecated // since 2.10
1596 public <T> T reportBadMerge(JsonDeserializer<?> deser) throws JsonMappingException {
1597 handleBadMerge(deser);
1598 return null;
Tatu Salorantab8f60292016-10-25 22:50:06 -07001599 }
1600
Tatu Saloranta2d318f62016-05-10 21:58:00 -07001601 /*
1602 /**********************************************************
1603 /* Methods for constructing semantic exceptions; usually not
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -07001604 /* to be called directly, call `handleXxx()` instead
Tatu Saloranta2d318f62016-05-10 21:58:00 -07001605 /**********************************************************
1606 */
1607
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001608 /**
Tatu Saloranta68245442016-05-21 18:08:41 -07001609 * Helper method for constructing {@link JsonMappingException} to indicate
Tatu Saloranta98dd0912016-05-15 23:13:44 -07001610 * that the token encountered was of type different than what <b>should</b>
1611 * be seen at that position, usually within a sequence of expected tokens.
1612 * Note that most of the time this method should NOT be directly called;
1613 * instead, {@link #reportWrongTokenException} should be called and will
1614 * call this method as necessary.
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001615 *
1616 * @since 2.9
Tatu Saloranta98dd0912016-05-15 23:13:44 -07001617 */
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001618 public JsonMappingException wrongTokenException(JsonParser p, JavaType targetType,
Tatu Saloranta79124862016-10-19 22:13:29 -07001619 JsonToken expToken, String extra)
Tatu Saloranta98dd0912016-05-15 23:13:44 -07001620 {
1621 String msg = String.format("Unexpected token (%s), expected %s",
1622 p.getCurrentToken(), expToken);
Tatu Saloranta79124862016-10-19 22:13:29 -07001623 msg = _colonConcat(msg, extra);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001624 return MismatchedInputException.from(p, targetType, msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001625 }
1626
1627 public JsonMappingException wrongTokenException(JsonParser p, Class<?> targetType,
Tatu Saloranta79124862016-10-19 22:13:29 -07001628 JsonToken expToken, String extra)
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001629 {
1630 String msg = String.format("Unexpected token (%s), expected %s",
1631 p.getCurrentToken(), expToken);
Tatu Saloranta79124862016-10-19 22:13:29 -07001632 msg = _colonConcat(msg, extra);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001633 return MismatchedInputException.from(p, targetType, msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001634 }
1635
1636 @Deprecated // since 2.9
1637 public JsonMappingException wrongTokenException(JsonParser p, JsonToken expToken,
1638 String msg)
1639 {
1640 return wrongTokenException(p, (JavaType) null, expToken, msg);
Tatu Saloranta98dd0912016-05-15 23:13:44 -07001641 }
1642
1643 /**
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001644 * Helper method for constructing exception to indicate that given JSON
1645 * Object field name was not in format to be able to deserialize specified
1646 * key type.
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001647 * Note that most of the time this method should NOT be called; instead,
1648 * {@link #handleWeirdKey} should be called which will call this method
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -07001649 * if necessary.
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001650 */
1651 public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue,
1652 String msg) {
1653 return InvalidFormatException.from(_parser,
Oliver Kopp68476802017-06-27 22:26:41 +03001654 String.format("Cannot deserialize Map key of type %s from String %s: %s",
Tatu Saloranta267abe12016-11-25 18:14:20 -08001655 ClassUtil.nameOf(keyClass), _quotedString(keyValue), msg),
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001656 keyValue, keyClass);
1657 }
1658
Tatu Saloranta2d318f62016-05-10 21:58:00 -07001659 /**
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001660 * Helper method for constructing exception to indicate that input JSON
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -07001661 * String was not suitable for deserializing into given target type.
1662 * Note that most of the time this method should NOT be called; instead,
1663 * {@link #handleWeirdStringValue} should be called which will call this method
1664 * if necessary.
1665 *
1666 * @param value String value from input being deserialized
1667 * @param instClass Type that String should be deserialized into
Tatu Saloranta94c56eb2019-01-18 20:45:25 -08001668 * @param msgBase Message that describes specific problem
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -07001669 *
1670 * @since 2.1
1671 */
1672 public JsonMappingException weirdStringException(String value, Class<?> instClass,
Tatu Saloranta94c56eb2019-01-18 20:45:25 -08001673 String msgBase) {
1674 final String msg = String.format("Cannot deserialize value of type %s from String %s: %s",
1675 ClassUtil.nameOf(instClass), _quotedString(value), msgBase);
1676 return InvalidFormatException.from(_parser, msg, value, instClass);
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -07001677 }
1678
1679 /**
1680 * Helper method for constructing exception to indicate that input JSON
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001681 * Number was not suitable for deserializing into given target type.
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -07001682 * Note that most of the time this method should NOT be called; instead,
1683 * {@link #handleWeirdNumberValue} should be called which will call this method
1684 * if necessary.
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001685 */
1686 public JsonMappingException weirdNumberException(Number value, Class<?> instClass,
1687 String msg) {
1688 return InvalidFormatException.from(_parser,
Oliver Kopp68476802017-06-27 22:26:41 +03001689 String.format("Cannot deserialize value of type %s from number %s: %s",
Tatu Saloranta267abe12016-11-25 18:14:20 -08001690 ClassUtil.nameOf(instClass), String.valueOf(value), msg),
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001691 value, instClass);
1692 }
Tatu Salorantab1041d02016-05-19 08:22:50 -07001693
1694 /**
Tatu Saloranta23a610d2017-07-26 16:57:29 -07001695 * Helper method for constructing exception to indicate that input JSON
1696 * token of type "native value" (see {@link JsonToken#VALUE_EMBEDDED_OBJECT})
1697 * is of incompatible type (and there is no delegating creator or such to use)
1698 * and can not be used to construct value of specified type (usually POJO).
1699 * Note that most of the time this method should NOT be called; instead,
1700 * {@link #handleWeirdNativeValue} should be called which will call this method
1701 *
1702 * @since 2.9
1703 */
1704 public JsonMappingException weirdNativeValueException(Object value, Class<?> instClass)
1705 {
1706 return InvalidFormatException.from(_parser, String.format(
1707"Cannot deserialize value of type %s from native value (`JsonToken.VALUE_EMBEDDED_OBJECT`) of type %s: incompatible types",
1708 ClassUtil.nameOf(instClass), ClassUtil.classNameOf(value)),
1709 value, instClass);
1710 }
1711
1712 /**
Tatu Salorantab1041d02016-05-19 08:22:50 -07001713 * Helper method for constructing instantiation exception for specified type,
1714 * to indicate problem with physically constructing instance of
1715 * specified class (missing constructor, exception from constructor)
1716 *<p>
Tatu Saloranta555cbeb2018-08-28 22:19:01 -07001717 * Note that most of the time this method should NOT be called directly; instead,
Tatu Salorantab1041d02016-05-19 08:22:50 -07001718 * {@link #handleInstantiationProblem} should be called which will call this method
1719 * if necessary.
1720 */
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001721 public JsonMappingException instantiationException(Class<?> instClass, Throwable cause) {
Tatu Saloranta555cbeb2018-08-28 22:19:01 -07001722 String excMsg;
1723 if (cause == null) {
1724 excMsg = "N/A";
Tatu Salorantaf6cf1812018-09-05 23:17:05 -07001725 } else if ((excMsg = ClassUtil.exceptionMessage(cause)) == null) {
Tatu Saloranta555cbeb2018-08-28 22:19:01 -07001726 excMsg = ClassUtil.nameOf(cause.getClass());
1727 }
Oliver Kopp68476802017-06-27 22:26:41 +03001728 String msg = String.format("Cannot construct instance of %s, problem: %s",
Tatu Saloranta555cbeb2018-08-28 22:19:01 -07001729 ClassUtil.nameOf(instClass), excMsg);
Tatu Saloranta39294f92018-09-04 22:25:50 -07001730 // [databind#2162]: use specific exception type as we don't know if it's
1731 // due to type definition, input, or neither
1732 return ValueInstantiationException.from(_parser, msg, constructType(instClass), cause);
Tatu Salorantab1041d02016-05-19 08:22:50 -07001733 }
1734
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001735 /**
Tatu Saloranta68245442016-05-21 18:08:41 -07001736 * Helper method for constructing instantiation exception for specified type,
1737 * to indicate that instantiation failed due to missing instantiator
1738 * (creator; constructor or factory method).
1739 *<p>
1740 * Note that most of the time this method should NOT be called; instead,
1741 * {@link #handleMissingInstantiator} should be called which will call this method
1742 * if necessary.
1743 */
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001744 public JsonMappingException instantiationException(Class<?> instClass, String msg0) {
Tatu Saloranta39294f92018-09-04 22:25:50 -07001745 // [databind#2162]: use specific exception type as we don't know if it's
1746 // due to type definition, input, or neither
1747 return ValueInstantiationException.from(_parser,
1748 String.format("Cannot construct instance of %s: %s",
1749 ClassUtil.nameOf(instClass), msg0),
1750 constructType(instClass));
Tatu Saloranta68245442016-05-21 18:08:41 -07001751 }
1752
Tatu Saloranta3e75d542017-05-02 22:45:54 -07001753 @Override
Tatu Saloranta52238562017-04-28 10:52:23 -07001754 public JsonMappingException invalidTypeIdException(JavaType baseType, String typeId,
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -07001755 String extraDesc) {
Tatu Saloranta52238562017-04-28 10:52:23 -07001756 String msg = String.format("Could not resolve type id '%s' as a subtype of %s",
Tatu Saloranta5f1bb5a2019-11-04 22:05:23 -08001757 typeId, ClassUtil.getTypeDescription(baseType));
Tatu Saloranta125ac182017-03-09 11:10:02 -08001758 return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, typeId);
Tatu Saloranta2d318f62016-05-10 21:58:00 -07001759 }
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -07001760
Tatu Saloranta5b8f0d92017-03-09 10:18:47 -08001761 /**
1762 * @since 2.9
1763 */
1764 public JsonMappingException missingTypeIdException(JavaType baseType,
1765 String extraDesc) {
1766 String msg = String.format("Missing type id when trying to resolve subtype of %s",
1767 baseType);
Tatu Saloranta125ac182017-03-09 11:10:02 -08001768 return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, null);
Tatu Saloranta5b8f0d92017-03-09 10:18:47 -08001769 }
1770
Tatu Saloranta34eaa4f2016-05-05 13:11:44 -07001771 /*
1772 /**********************************************************
Tatu Saloranta851092c2016-05-21 20:08:40 -07001773 /* Deprecated exception factory methods
Tatu Saloranta34eaa4f2016-05-05 13:11:44 -07001774 /**********************************************************
1775 */
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001776
Tatu Saloranta7a4193f2016-05-05 12:55:05 -07001777 /**
Tatu Saloranta7fc32382014-12-26 17:19:09 -08001778 * @since 2.5
Tatu Saloranta2ffca932016-05-05 12:23:14 -07001779 *
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001780 * @deprecated Since 2.8 use {@link #handleUnknownTypeId} instead
Tatu Saloranta7fc32382014-12-26 17:19:09 -08001781 */
Tatu Saloranta2ffca932016-05-05 12:23:14 -07001782 @Deprecated
Tatu Saloranta7fc32382014-12-26 17:19:09 -08001783 public JsonMappingException unknownTypeException(JavaType type, String id,
Tatu Saloranta43fbd712016-11-09 21:43:27 -08001784 String extraDesc)
1785 {
Tatu Saloranta8c3eb032016-04-20 22:52:38 -07001786 String msg = String.format("Could not resolve type id '%s' into a subtype of %s",
Tatu Saloranta5f1bb5a2019-11-04 22:05:23 -08001787 id, ClassUtil.getTypeDescription(type));
Tatu Saloranta79124862016-10-19 22:13:29 -07001788 msg = _colonConcat(msg, extraDesc);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001789 return MismatchedInputException.from(_parser, type, msg);
Tatu Saloranta7fc32382014-12-26 17:19:09 -08001790 }
1791
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -07001792 /**
1793 * Helper method for constructing exception to indicate that end-of-input was
1794 * reached while still expecting more tokens to deserialize value of specified type.
1795 *
1796 * @deprecated Since 2.8; currently no way to catch EOF at databind level
1797 */
1798 @Deprecated
1799 public JsonMappingException endOfInputException(Class<?> instClass) {
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001800 return MismatchedInputException.from(_parser, instClass,
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001801 "Unexpected end-of-input when trying to deserialize a "+instClass.getName());
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -07001802 }
1803
Tatu Saloranta06c20b12012-01-29 21:36:52 -08001804 /*
1805 /**********************************************************
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001806 /* Deprecated methods for constructing, throwing non-specific
1807 /* JsonMappingExceptions: as of 2.9, should use more specific
1808 /* ones.
1809 /**********************************************************
1810 */
1811
1812 /**
1813 * Fallback method that may be called if no other <code>reportXxx</code>
1814 * is applicable -- but only in that case.
1815 *
1816 * @since 2.8
1817 *
Tatu Salorantad9b0cae2017-04-24 22:49:03 -07001818 * @deprecated Since 2.9: use a more specific method, or {@link #reportBadDefinition(JavaType, String)},
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001819 * or {@link #reportInputMismatch} instead
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001820 */
1821 @Deprecated // since 2.9
1822 public void reportMappingException(String msg, Object... msgArgs)
1823 throws JsonMappingException
1824 {
Tatu Salorantae27ec2d2016-10-24 22:44:16 -07001825 throw JsonMappingException.from(getParser(), _format(msg, msgArgs));
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001826 }
1827
1828 /**
1829 * Helper method for constructing generic mapping exception with specified
1830 * message and current location information.
1831 * Note that application code should almost always call
1832 * one of <code>handleXxx</code> methods, or {@link #reportMappingException(String, Object...)}
1833 * instead.
1834 *
1835 * @since 2.6
1836 *
1837 * @deprecated Since 2.9 use more specific error reporting methods instead
1838 */
1839 @Deprecated
1840 public JsonMappingException mappingException(String message) {
1841 return JsonMappingException.from(getParser(), message);
1842 }
1843
1844 /**
1845 * Helper method for constructing generic mapping exception with specified
1846 * message and current location information
1847 * Note that application code should almost always call
1848 * one of <code>handleXxx</code> methods, or {@link #reportMappingException(String, Object...)}
1849 * instead.
1850 *
1851 * @since 2.6
1852 *
1853 * @deprecated Since 2.9 use more specific error reporting methods instead
1854 */
1855 @Deprecated
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001856 public JsonMappingException mappingException(String msg, Object... msgArgs) {
1857 return JsonMappingException.from(getParser(), _format(msg, msgArgs));
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001858 }
1859
1860 /**
1861 * Helper method for constructing generic mapping exception for specified type
1862 *
1863 * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
1864 */
1865 @Deprecated
1866 public JsonMappingException mappingException(Class<?> targetClass) {
1867 return mappingException(targetClass, _parser.getCurrentToken());
1868 }
1869
1870 /**
1871 * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
1872 */
1873 @Deprecated
1874 public JsonMappingException mappingException(Class<?> targetClass, JsonToken token) {
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001875 return JsonMappingException.from(_parser,
Oliver Kopp68476802017-06-27 22:26:41 +03001876 String.format("Cannot deserialize instance of %s out of %s token",
Tatu Saloranta9a81cf12017-09-18 22:04:55 -07001877 ClassUtil.nameOf(targetClass), token));
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001878 }
1879
1880 /*
1881 /**********************************************************
Tatu Saloranta851092c2016-05-21 20:08:40 -07001882 /* Other internal methods
Tatu Saloranta06c20b12012-01-29 21:36:52 -08001883 /**********************************************************
1884 */
1885
1886 protected DateFormat getDateFormat()
1887 {
Tatu Saloranta3b88a6b2012-02-24 09:53:59 -08001888 if (_dateFormat != null) {
1889 return _dateFormat;
Tatu Saloranta06c20b12012-01-29 21:36:52 -08001890 }
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -08001891 /* 24-Feb-2012, tatu: At this point, all timezone configuration
Cowtowncoder8d0d6e42015-01-22 15:36:13 -08001892 * should have occurred, with respect to default dateformat
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -08001893 * and timezone configuration. But we still better clone
1894 * an instance as formatters may be stateful.
Tatu Saloranta3b88a6b2012-02-24 09:53:59 -08001895 */
1896 DateFormat df = _config.getDateFormat();
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -08001897 _dateFormat = df = (DateFormat) df.clone();
Tatu Saloranta3b88a6b2012-02-24 09:53:59 -08001898 return df;
Tatu Saloranta06c20b12012-01-29 21:36:52 -08001899 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001900}