blob: 8931a9640d1d1cde9eda3f2a3a99330bd8c3638c [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 Saloranta4eb4f792020-01-20 15:01:45 -0800158 if (df == null) {
159 throw new NullPointerException("Cannot pass null DeserializerFactory");
160 }
161 _factory = df;
Tatu Saloranta43fbd712016-11-09 21:43:27 -0800162 if (cache == null) {
163 cache = new DeserializerCache();
164 }
165 _cache = cache;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800166 _featureFlags = 0;
167 _config = null;
168 _injectableValues = null;
169 _view = null;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700170 _attributes = null;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800171 }
172
173 protected DeserializationContext(DeserializationContext src,
174 DeserializerFactory factory)
175 {
176 _cache = src._cache;
177 _factory = factory;
178
179 _config = src._config;
180 _featureFlags = src._featureFlags;
181 _view = src._view;
182 _parser = src._parser;
183 _injectableValues = src._injectableValues;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700184 _attributes = src._attributes;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800185 }
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700186
187 /**
188 * Constructor used for creating actual per-call instances.
189 */
Tatu Saloranta060ce112012-02-01 22:18:09 -0800190 protected DeserializationContext(DeserializationContext src,
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700191 DeserializationConfig config, JsonParser p,
Tatu Saloranta060ce112012-02-01 22:18:09 -0800192 InjectableValues injectableValues)
193 {
194 _cache = src._cache;
195 _factory = src._factory;
196
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800197 _config = config;
Tatu Salorantae3ae58e2012-01-28 23:08:16 -0800198 _featureFlags = config.getDeserializationFeatures();
Tatu Salorantab2d3c7d2012-01-27 21:41:48 -0800199 _view = config.getActiveView();
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700200 _parser = p;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800201 _injectableValues = injectableValues;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700202 _attributes = config.getAttributes();
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800203 }
Tatu Saloranta9439a312013-03-02 13:13:09 -0800204
Tatu Saloranta23328aa2014-10-28 22:38:15 -0700205 /**
206 * Copy-constructor for use with <code>copy()</code> by {@link ObjectMapper#copy()}
207 */
208 protected DeserializationContext(DeserializationContext src) {
209 _cache = new DeserializerCache();
210 _factory = src._factory;
211
212 _config = src._config;
213 _featureFlags = src._featureFlags;
214 _view = src._view;
215 _injectableValues = null;
216 }
217
Tatu Saloranta9439a312013-03-02 13:13:09 -0800218 /*
219 /**********************************************************
220 /* DatabindContext implementation
221 /**********************************************************
222 */
223
224 @Override
225 public DeserializationConfig getConfig() { return _config; }
226
227 @Override
228 public final Class<?> getActiveView() { return _view; }
229
230 @Override
Tatu Salorantaa5301ba2015-12-11 09:47:09 -0800231 public final boolean canOverrideAccessModifiers() {
232 return _config.canOverrideAccessModifiers();
233 }
234
235 @Override
236 public final boolean isEnabled(MapperFeature feature) {
237 return _config.isEnabled(feature);
238 }
239
240 @Override
241 public final JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType) {
242 return _config.getDefaultPropertyFormat(baseType);
243 }
Tatu Saloranta4fdbb692016-04-16 21:41:14 -0700244
Tatu Salorantaa5301ba2015-12-11 09:47:09 -0800245 @Override
Tatu Saloranta9439a312013-03-02 13:13:09 -0800246 public final AnnotationIntrospector getAnnotationIntrospector() {
247 return _config.getAnnotationIntrospector();
248 }
249
250 @Override
251 public final TypeFactory getTypeFactory() {
252 return _config.getTypeFactory();
253 }
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700254
Cowtowncoder41bbc962015-06-19 17:16:08 -0700255 /**
256 * Method for accessing default Locale to use: convenience method for
257 *<pre>
258 * getConfig().getLocale();
259 *</pre>
260 */
261 @Override
262 public Locale getLocale() {
263 return _config.getLocale();
264 }
265
266 /**
267 * Method for accessing default TimeZone to use: convenience method for
268 *<pre>
269 * getConfig().getTimeZone();
270 *</pre>
271 */
272 @Override
273 public TimeZone getTimeZone() {
274 return _config.getTimeZone();
275 }
276
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700277 /*
278 /**********************************************************
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800279 /* Access to per-call state, like generic attributes (2.3+)
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700280 /**********************************************************
281 */
282
283 @Override
284 public Object getAttribute(Object key) {
285 return _attributes.getAttribute(key);
286 }
287
288 @Override
289 public DeserializationContext setAttribute(Object key, Object value)
290 {
291 _attributes = _attributes.withPerCallAttribute(key, value);
292 return this;
293 }
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800294
295 /**
296 * Accessor to {@link JavaType} of currently contextualized
297 * {@link ContextualDeserializer}, if any.
298 * This is sometimes useful for generic {@link JsonDeserializer}s that
299 * do not get passed (or do not retain) type information when being
300 * constructed: happens for example for deserializers constructed
301 * from annotations.
302 *
303 * @since 2.5
304 *
305 * @return Type of {@link ContextualDeserializer} being contextualized,
306 * if process is on-going; null if not.
307 */
308 public JavaType getContextualType() {
309 return (_currentType == null) ? null : _currentType.value();
310 }
311
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800312 /*
313 /**********************************************************
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800314 /* Public API, config setting accessors
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800315 /**********************************************************
316 */
317
318 /**
Dmitry Katsuboe70c66f2012-09-03 16:00:30 +0200319 * Method for getting current {@link DeserializerFactory}.
320 */
321 public DeserializerFactory getFactory() {
322 return _factory;
323 }
Tatu Saloranta9439a312013-03-02 13:13:09 -0800324
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800325 /**
326 * Convenience method for checking whether specified on/off
327 * feature is enabled
328 */
Tatu9610aff2012-02-02 11:30:08 -0800329 public final boolean isEnabled(DeserializationFeature feat) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800330 /* 03-Dec-2010, tatu: minor shortcut; since this is called quite often,
331 * let's use a local copy of feature settings:
332 */
333 return (_featureFlags & feat.getMask()) != 0;
334 }
335
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800336 /**
Cowtowncoder23e52ab2015-05-19 17:53:26 -0700337 * Bulk access method for getting the bit mask of all {@link DeserializationFeature}s
338 * that are enabled.
339 *
340 * @since 2.6
341 */
342 public final int getDeserializationFeatures() {
343 return _featureFlags;
344 }
345
346 /**
347 * Bulk access method for checking that all features specified by
Tatu Saloranta0ac36ba2013-08-21 18:08:51 -0700348 * mask are enabled.
349 *
350 * @since 2.3
351 */
352 public final boolean hasDeserializationFeatures(int featureMask) {
Cowtowncoder23e52ab2015-05-19 17:53:26 -0700353 return (_featureFlags & featureMask) == featureMask;
354 }
355
356 /**
357 * Bulk access method for checking that at least one of features specified by
358 * mask is enabled.
359 *
360 * @since 2.6
361 */
362 public final boolean hasSomeOfFeatures(int featureMask) {
363 return (_featureFlags & featureMask) != 0;
Tatu Saloranta0ac36ba2013-08-21 18:08:51 -0700364 }
365
366 /**
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800367 * Method for accessing the currently active parser.
368 * May be different from the outermost parser
369 * when content is buffered.
370 *<p>
371 * Use of this method is discouraged: if code has direct access
372 * to the active parser, that should be used instead.
373 */
374 public final JsonParser getParser() { return _parser; }
375
376 public final Object findInjectableValue(Object valueId,
377 BeanProperty forProperty, Object beanInstance)
Tatu Saloranta68440372016-10-29 17:06:05 -0700378 throws JsonMappingException
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800379 {
380 if (_injectableValues == null) {
Tatu Saloranta68440372016-10-29 17:06:05 -0700381 reportBadDefinition(ClassUtil.classOf(valueId), String.format(
Oliver Kopp68476802017-06-27 22:26:41 +0300382"No 'injectableValues' configured, cannot inject value with id [%s]", valueId));
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800383 }
384 return _injectableValues.findInjectableValue(valueId, this, forProperty, beanInstance);
385 }
Tatu Salorantab2d3c7d2012-01-27 21:41:48 -0800386
Tatu Saloranta060ce112012-02-01 22:18:09 -0800387 /**
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800388 * Convenience method for accessing the default Base64 encoding
389 * used for decoding base64 encoded binary content.
390 * Same as calling:
391 *<pre>
392 * getConfig().getBase64Variant();
393 *</pre>
394 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800395 public final Base64Variant getBase64Variant() {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800396 return _config.getBase64Variant();
397 }
398
Tatu Saloranta060ce112012-02-01 22:18:09 -0800399 /**
400 * Convenience method, functionally equivalent to:
401 *<pre>
402 * getConfig().getNodeFactory();
403 * </pre>
404 */
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800405 public final JsonNodeFactory getNodeFactory() {
406 return _config.getNodeFactory();
407 }
408
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800409 /*
410 /**********************************************************
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800411 /* Public API, pass-through to DeserializerCache
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800412 /**********************************************************
413 */
Tatuc3a73d02012-01-31 12:45:49 -0800414
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800415 /**
Tatu Saloranta060ce112012-02-01 22:18:09 -0800416 * Method for checking whether we could find a deserializer
417 * for given type.
Cowtowncodera2e27202014-11-25 17:07:52 -0800418 *
Tatu Salorantaaf263c32013-10-24 16:18:50 -0700419 * @param type
420 * @since 2.3
Tatu Saloranta060ce112012-02-01 22:18:09 -0800421 */
Tatu Salorantaaf263c32013-10-24 16:18:50 -0700422 public boolean hasValueDeserializerFor(JavaType type, AtomicReference<Throwable> cause) {
423 try {
424 return _cache.hasValueDeserializerFor(this, _factory, type);
425 } catch (JsonMappingException e) {
426 if (cause != null) {
427 cause.set(e);
428 }
429 } catch (RuntimeException e) {
430 if (cause == null) { // earlier behavior
431 throw e;
432 }
433 cause.set(e);
434 }
435 return false;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800436 }
437
Tatu Saloranta060ce112012-02-01 22:18:09 -0800438 /**
Tatuc3a73d02012-01-31 12:45:49 -0800439 * Method for finding a value deserializer, and creating a contextual
440 * version if necessary, for value reached via specified property.
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800441 */
Tatuc3a73d02012-01-31 12:45:49 -0800442 @SuppressWarnings("unchecked")
443 public final JsonDeserializer<Object> findContextualValueDeserializer(JavaType type,
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700444 BeanProperty prop) throws JsonMappingException
Tatuc3a73d02012-01-31 12:45:49 -0800445 {
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700446 JsonDeserializer<Object> deser = _cache.findValueDeserializer(this, _factory, type);
Tatuc3a73d02012-01-31 12:45:49 -0800447 if (deser != null) {
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800448 deser = (JsonDeserializer<Object>) handleSecondaryContextualization(deser, prop, type);
Tatuc3a73d02012-01-31 12:45:49 -0800449 }
450 return deser;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800451 }
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700452
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800453 /**
Cowtowncodera2e27202014-11-25 17:07:52 -0800454 * Variant that will try to locate deserializer for current type, but without
455 * performing any contextualization (unlike {@link #findContextualValueDeserializer})
456 * or checking for need to create a {@link TypeDeserializer} (unlike
457 * {@link #findRootValueDeserializer(JavaType)}.
458 * This method is usually called from within {@link ResolvableDeserializer#resolve},
459 * and expectation is that caller then calls either
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800460 * {@link #handlePrimaryContextualization(JsonDeserializer, BeanProperty, JavaType)} or
461 * {@link #handleSecondaryContextualization(JsonDeserializer, BeanProperty, JavaType)} at a
Cowtowncodera2e27202014-11-25 17:07:52 -0800462 * later point, as necessary.
463 *
464 * @since 2.5
465 */
466 public final JsonDeserializer<Object> findNonContextualValueDeserializer(JavaType type)
467 throws JsonMappingException
468 {
469 return _cache.findValueDeserializer(this, _factory, type);
470 }
471
472 /**
Tatuc3a73d02012-01-31 12:45:49 -0800473 * Method for finding a deserializer for root-level value.
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800474 */
Tatuc3a73d02012-01-31 12:45:49 -0800475 @SuppressWarnings("unchecked")
Tatu Saloranta9b9d0432012-01-30 09:20:26 -0800476 public final JsonDeserializer<Object> findRootValueDeserializer(JavaType type)
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700477 throws JsonMappingException
Tatuc3a73d02012-01-31 12:45:49 -0800478 {
Tatu Saloranta060ce112012-02-01 22:18:09 -0800479 JsonDeserializer<Object> deser = _cache.findValueDeserializer(this,
480 _factory, type);
Tatuc3a73d02012-01-31 12:45:49 -0800481 if (deser == null) { // can this occur?
482 return null;
483 }
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800484 deser = (JsonDeserializer<Object>) handleSecondaryContextualization(deser, null, type);
Tatuc3a73d02012-01-31 12:45:49 -0800485 TypeDeserializer typeDeser = _factory.findTypeDeserializer(_config, type);
486 if (typeDeser != null) {
487 // important: contextualize to indicate this is for root value
488 typeDeser = typeDeser.forProperty(null);
489 return new TypeWrappedDeserializer(typeDeser, deser);
490 }
491 return deser;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800492 }
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800493
494 /**
495 * Convenience method, functionally same as:
496 *<pre>
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700497 * getDeserializerProvider().findKeyDeserializer(getConfig(), prop.getType(), prop);
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800498 *</pre>
499 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800500 public final KeyDeserializer findKeyDeserializer(JavaType keyType,
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700501 BeanProperty prop) throws JsonMappingException {
Tatu Saloranta060ce112012-02-01 22:18:09 -0800502 KeyDeserializer kd = _cache.findKeyDeserializer(this,
503 _factory, keyType);
Tatud0bb3152012-01-31 13:04:06 -0800504 // Second: contextualize?
505 if (kd instanceof ContextualKeyDeserializer) {
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700506 kd = ((ContextualKeyDeserializer) kd).createContextual(this, prop);
Tatud0bb3152012-01-31 13:04:06 -0800507 }
508 return kd;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800509 }
510
Tatub37ff332012-01-24 16:19:36 -0800511 /*
512 /**********************************************************
Tatu Saloranta34a8adf2012-02-08 22:07:36 -0800513 /* Public API, ObjectId handling
514 /**********************************************************
515 */
516
517 /**
518 * Method called to find and return entry corresponding to given
519 * Object Id: will add an entry if necessary, and never returns null
520 */
Pascal GĂ©linas184cae32014-02-05 17:35:56 -0500521 public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> generator, ObjectIdResolver resolver);
522
Pascal GĂ©linas096e02b2013-12-18 17:21:42 -0500523 /**
524 * Method called to ensure that every object id encounter during processing
525 * are resolved.
526 *
527 * @throws UnresolvedForwardReference
528 */
529 public abstract void checkUnresolvedObjectId()
530 throws UnresolvedForwardReference;
531
Tatu Salorantabf5e0fa2012-03-08 21:45:30 -0800532 /*
533 /**********************************************************
534 /* Public API, type handling
535 /**********************************************************
536 */
537
538 /**
539 * Convenience method, functionally equivalent to:
540 *<pre>
541 * getConfig().constructType(cls);
542 * </pre>
543 */
544 public final JavaType constructType(Class<?> cls) {
Tatu Saloranta816bbed2016-10-05 21:13:12 -0700545 return (cls == null) ? null : _config.constructType(cls);
Tatu Salorantabf5e0fa2012-03-08 21:45:30 -0800546 }
547
548 /**
Cowtowncodera5bd0a22015-06-25 15:27:07 -0700549 * Helper method that is to be used when resolving basic class name into
550 * Class instance, the reason being that it may be necessary to work around
551 * various ClassLoader limitations, as well as to handle primitive type
552 * signatures.
553 *
554 * @since 2.6
Tatu Salorantabf5e0fa2012-03-08 21:45:30 -0800555 */
556 public Class<?> findClass(String className) throws ClassNotFoundException
557 {
558 // By default, delegate to ClassUtil: can be overridden with custom handling
Cowtowncodera5bd0a22015-06-25 15:27:07 -0700559 return getTypeFactory().findClass(className);
Tatu Salorantabf5e0fa2012-03-08 21:45:30 -0800560 }
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800561
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800562 /*
563 /**********************************************************
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800564 /* Public API, helper object recycling
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800565 /**********************************************************
566 */
567
568 /**
569 * Method that can be used to get access to a reusable ObjectBuffer,
570 * useful for efficiently constructing Object arrays and Lists.
571 * Note that leased buffers should be returned once deserializer
572 * is done, to allow for reuse during same round of deserialization.
573 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800574 public final ObjectBuffer leaseObjectBuffer()
575 {
576 ObjectBuffer buf = _objectBuffer;
577 if (buf == null) {
578 buf = new ObjectBuffer();
579 } else {
580 _objectBuffer = null;
581 }
582 return buf;
583 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800584
585 /**
586 * Method to call to return object buffer previously leased with
587 * {@link #leaseObjectBuffer}.
588 *
589 * @param buf Returned object buffer
590 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800591 public final void returnObjectBuffer(ObjectBuffer buf)
592 {
593 /* Already have a reusable buffer? Let's retain bigger one
594 * (or if equal, favor newer one, shorter life-cycle)
595 */
596 if (_objectBuffer == null
597 || buf.initialCapacity() >= _objectBuffer.initialCapacity()) {
598 _objectBuffer = buf;
599 }
600 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800601
602 /**
603 * Method for accessing object useful for building arrays of
604 * primitive types (such as int[]).
605 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800606 public final ArrayBuilders getArrayBuilders()
607 {
608 if (_arrayBuilders == null) {
609 _arrayBuilders = new ArrayBuilders();
610 }
611 return _arrayBuilders;
612 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800613
614 /*
615 /**********************************************************
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700616 /* Extended API: handler instantiation
617 /**********************************************************
618 */
619
620 public abstract JsonDeserializer<Object> deserializerInstance(Annotated annotated,
621 Object deserDef)
622 throws JsonMappingException;
623
624 public abstract KeyDeserializer keyDeserializerInstance(Annotated annotated,
625 Object deserDef)
626 throws JsonMappingException;
627
628 /*
629 /**********************************************************
630 /* Extended API: resolving contextual deserializers; called
631 /* by structured deserializers for their value/component
632 /* deserializers
633 /**********************************************************
634 */
635
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700636 /**
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700637 * Method called for primary property deserializers (ones
Tatu Saloranta59fe29c2013-09-05 22:37:06 -0700638 * directly created to deserialize values of a POJO property),
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700639 * to handle details of resolving
640 * {@link ContextualDeserializer} with given property context.
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700641 *
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700642 * @param prop Property for which the given primary deserializer is used; never null.
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700643 *
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800644 * @since 2.5
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700645 */
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700646 public JsonDeserializer<?> handlePrimaryContextualization(JsonDeserializer<?> deser,
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800647 BeanProperty prop, JavaType type)
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700648 throws JsonMappingException
649 {
Cowtowncodera2e27202014-11-25 17:07:52 -0800650 if (deser instanceof ContextualDeserializer) {
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800651 _currentType = new LinkedNode<JavaType>(type, _currentType);
652 try {
653 deser = ((ContextualDeserializer) deser).createContextual(this, prop);
654 } finally {
655 _currentType = _currentType.next();
656 }
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700657 }
658 return deser;
659 }
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700660
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700661 /**
662 * Method called for secondary property deserializers (ones
663 * NOT directly created to deal with an annotatable POJO property,
664 * but instead created as a component -- such as value deserializers
665 * for structured types, or deserializers for root values)
666 * to handle details of resolving
667 * {@link ContextualDeserializer} with given property context.
Tatu Saloranta59fe29c2013-09-05 22:37:06 -0700668 * Given that these deserializers are not directly related to given property
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700669 * (or, in case of root value property, to any property), annotations
670 * accessible may or may not be relevant.
671 *
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700672 * @param prop Property for which deserializer is used, if any; null
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700673 * when deserializing root values
674 *
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800675 * @since 2.5
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700676 */
677 public JsonDeserializer<?> handleSecondaryContextualization(JsonDeserializer<?> deser,
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800678 BeanProperty prop, JavaType type)
679 throws JsonMappingException
680 {
681 if (deser instanceof ContextualDeserializer) {
682 _currentType = new LinkedNode<JavaType>(type, _currentType);
683 try {
684 deser = ((ContextualDeserializer) deser).createContextual(this, prop);
685 } finally {
686 _currentType = _currentType.next();
687 }
688 }
689 return deser;
690 }
691
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700692 /*
693 /**********************************************************
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800694 /* Parsing methods that may use reusable/-cyclable objects
695 /**********************************************************
696 */
697
698 /**
699 * Convenience method for parsing a Date from given String, using
700 * currently configured date format (accessed using
701 * {@link DeserializationConfig#getDateFormat()}).
702 *<p>
703 * Implementation will handle thread-safety issues related to
704 * date formats such that first time this method is called,
705 * date format is cloned, and cloned instance will be retained
706 * for use during this deserialization round.
707 */
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700708 public Date parseDate(String dateStr) throws IllegalArgumentException
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800709 {
710 try {
Tatu Salorantaef00ac62013-11-03 09:56:39 -0800711 DateFormat df = getDateFormat();
712 return df.parse(dateStr);
Tatu Salorantaaa512742012-02-22 22:51:33 -0800713 } catch (ParseException e) {
Tatu Saloranta8e9d4b22015-05-01 21:26:32 -0700714 throw new IllegalArgumentException(String.format(
Tatu Salorantaf6cf1812018-09-05 23:17:05 -0700715 "Failed to parse Date value '%s': %s", dateStr,
716 ClassUtil.exceptionMessage(e)));
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800717 }
718 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800719
720 /**
721 * Convenience method for constructing Calendar instance set
722 * to specified time, to be modified and used by caller.
723 */
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700724 public Calendar constructCalendar(Date d) {
725 // 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 -0800726 Calendar c = Calendar.getInstance(getTimeZone());
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800727 c.setTime(d);
728 return c;
729 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800730
731 /*
732 /**********************************************************
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700733 /* Convenience methods for reading parsed values
734 /**********************************************************
735 */
736
737 /**
738 * Convenience method that may be used by composite or container deserializers,
739 * for reading one-off values contained (for sequences, it is more efficient
740 * to actually fetch deserializer once for the whole collection).
741 *<p>
742 * NOTE: when deserializing values of properties contained in composite types,
743 * rather use {@link #readPropertyValue(JsonParser, BeanProperty, Class)};
744 * this method does not allow use of contextual annotations.
745 *
746 * @since 2.4
747 */
748 public <T> T readValue(JsonParser p, Class<T> type) throws IOException {
749 return readValue(p, getTypeFactory().constructType(type));
750 }
751
752 /**
753 * @since 2.4
754 */
755 @SuppressWarnings("unchecked")
756 public <T> T readValue(JsonParser p, JavaType type) throws IOException {
757 JsonDeserializer<Object> deser = findRootValueDeserializer(type);
758 if (deser == null) {
Tatu Salorantac1478ac2016-09-29 08:17:03 -0700759 reportBadDefinition(type,
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700760 "Could not find JsonDeserializer for type "+ClassUtil.getTypeDescription(type));
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700761 }
762 return (T) deser.deserialize(p, this);
763 }
764
765 /**
766 * Convenience method that may be used by composite or container deserializers,
767 * for reading one-off values for the composite type, taking into account
768 * annotations that the property (passed to this method -- usually property that
769 * has custom serializer that called this method) has.
770 *
771 * @since 2.4
772 */
773 public <T> T readPropertyValue(JsonParser p, BeanProperty prop, Class<T> type) throws IOException {
774 return readPropertyValue(p, prop, getTypeFactory().constructType(type));
775 }
776
777 /**
778 * @since 2.4
779 */
780 @SuppressWarnings("unchecked")
781 public <T> T readPropertyValue(JsonParser p, BeanProperty prop, JavaType type) throws IOException {
782 JsonDeserializer<Object> deser = findContextualValueDeserializer(type, prop);
783 if (deser == null) {
Tatu Salorantac1478ac2016-09-29 08:17:03 -0700784 return reportBadDefinition(type, String.format(
Tatu Saloranta851092c2016-05-21 20:08:40 -0700785 "Could not find JsonDeserializer for type %s (via property %s)",
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700786 ClassUtil.getTypeDescription(type), ClassUtil.nameOf(prop)));
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700787 }
788 return (T) deser.deserialize(p, this);
789 }
Tatu Saloranta5ae6e4b2015-10-05 21:49:01 -0700790
Tatu Saloranta7904f922019-09-11 15:03:50 -0700791 /**
792 * @since 2.10
793 */
794 public JsonNode readTree(JsonParser p) throws IOException {
795 JsonToken t = p.currentToken();
796 if (t == null) {
797 t = p.nextToken();
798 if (t == null) {
799 return getNodeFactory().missingNode();
800 }
801 }
802 if (t == JsonToken.VALUE_NULL) {
803 return getNodeFactory().nullNode();
804 }
805 return (JsonNode) findRootValueDeserializer(_config.constructType(JsonNode.class))
806 .deserialize(p, this);
807 }
808
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700809 /*
810 /**********************************************************
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700811 /* Methods for problem handling
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800812 /**********************************************************
813 */
814
815 /**
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700816 * Method that deserializers should call if they encounter an unrecognized
817 * property (and once that is not explicitly designed as ignorable), to
818 * inform possibly configured {@link DeserializationProblemHandler}s and
819 * let it handle the problem.
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800820 *
821 * @return True if there was a configured problem handler that was able to handle the
Tatu Saloranta0e3b3832012-01-22 22:08:20 -0800822 * problem
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800823 */
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700824 public boolean handleUnknownProperty(JsonParser p, JsonDeserializer<?> deser,
Tatu Saloranta060ce112012-02-01 22:18:09 -0800825 Object instanceOrClass, String propName)
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700826 throws IOException
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800827 {
828 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700829 while (h != null) {
830 // Can bail out if it's handled
831 if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) {
832 return true;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800833 }
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700834 h = h.next();
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800835 }
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700836 // Nope, not handled. Potentially that's a problem...
837 if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
838 p.skipChildren();
839 return true;
840 }
841 // Do we know properties that are expected instead?
842 Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames();
843 throw UnrecognizedPropertyException.from(_parser,
844 instanceOrClass, propName, propIds);
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800845 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800846
847 /**
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700848 * Method that deserializers should call if they encounter a String value
Oliver Kopp5e3bf082017-06-27 14:12:19 +0300849 * that cannot be converted to expected key of a {@link java.util.Map}
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700850 * valued property.
851 * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue}
852 * on configured handlers, if any, to allow for recovery; if recovery does not
853 * succeed, will throw {@link InvalidFormatException} with given message.
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700854 *
855 * @param keyClass Expected type for key
856 * @param keyValue String value from which to deserialize key
857 * @param msg Error message template caller wants to use if exception is to be thrown
858 * @param msgArgs Optional arguments to use for message, if any
859 *
860 * @return Key value to use
861 *
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700862 * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700863 *
864 * @since 2.8
865 */
866 public Object handleWeirdKey(Class<?> keyClass, String keyValue,
867 String msg, Object... msgArgs)
868 throws IOException
869 {
870 // but if not handled, just throw exception
Tatu Saloranta79124862016-10-19 22:13:29 -0700871 msg = _format(msg, msgArgs);
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700872 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700873 while (h != null) {
874 // Can bail out if it's handled
875 Object key = h.value().handleWeirdKey(this, keyClass, keyValue, msg);
Tatu Saloranta2d318f62016-05-10 21:58:00 -0700876 if (key != DeserializationProblemHandler.NOT_HANDLED) {
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700877 // Sanity check for broken handlers, otherwise nasty to debug:
878 if ((key == null) || keyClass.isInstance(key)) {
879 return key;
880 }
881 throw weirdStringException(keyValue, keyClass, String.format(
882 "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700883 ClassUtil.getClassDescription(keyClass),
884 ClassUtil.getClassDescription(key)
885 ));
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700886 }
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700887 h = h.next();
Tatu Saloranta1e5fd122016-05-09 23:26:30 -0700888 }
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -0700889 throw weirdKeyException(keyClass, keyValue, msg);
890 }
891
892 /**
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -0700893 * Method that deserializers should call if they encounter a String value
Oliver Kopp5e3bf082017-06-27 14:12:19 +0300894 * that cannot be converted to target property type, in cases where some
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -0700895 * String values could be acceptable (either with different settings,
896 * or different value).
897 * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdStringValue}
898 * on configured handlers, if any, to allow for recovery; if recovery does not
899 * succeed, will throw {@link InvalidFormatException} with given message.
900 *
901 * @param targetClass Type of property into which incoming number should be converted
902 * @param value String value from which to deserialize property value
903 * @param msg Error message template caller wants to use if exception is to be thrown
904 * @param msgArgs Optional arguments to use for message, if any
905 *
906 * @return Property value to use
907 *
908 * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
909 *
910 * @since 2.8
911 */
912 public Object handleWeirdStringValue(Class<?> targetClass, String value,
913 String msg, Object... msgArgs)
914 throws IOException
915 {
916 // but if not handled, just throw exception
Tatu Saloranta79124862016-10-19 22:13:29 -0700917 msg = _format(msg, msgArgs);
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -0700918 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
919 while (h != null) {
920 // Can bail out if it's handled
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700921 Object instance = h.value().handleWeirdStringValue(this, targetClass, value, msg);
922 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
923 // Sanity check for broken handlers, otherwise nasty to debug:
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -0700924 if (_isCompatible(targetClass, instance)) {
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700925 return instance;
926 }
927 throw weirdStringException(value, targetClass, String.format(
928 "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700929 ClassUtil.getClassDescription(targetClass),
930 ClassUtil.getClassDescription(instance)
931 ));
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -0700932 }
933 h = h.next();
934 }
935 throw weirdStringException(value, targetClass, msg);
936 }
937
938 /**
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700939 * Method that deserializers should call if they encounter a numeric value
Oliver Kopp5e3bf082017-06-27 14:12:19 +0300940 * that cannot be converted to target property type, in cases where some
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700941 * numeric values could be acceptable (either with different settings,
942 * or different numeric value).
943 * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue}
944 * on configured handlers, if any, to allow for recovery; if recovery does not
945 * succeed, will throw {@link InvalidFormatException} with given message.
946 *
947 * @param targetClass Type of property into which incoming number should be converted
948 * @param value Number value from which to deserialize property value
949 * @param msg Error message template caller wants to use if exception is to be thrown
950 * @param msgArgs Optional arguments to use for message, if any
951 *
952 * @return Property value to use
953 *
954 * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
955 *
956 * @since 2.8
957 */
958 public Object handleWeirdNumberValue(Class<?> targetClass, Number value,
959 String msg, Object... msgArgs)
960 throws IOException
961 {
Tatu Saloranta79124862016-10-19 22:13:29 -0700962 msg = _format(msg, msgArgs);
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700963 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
964 while (h != null) {
965 // Can bail out if it's handled
966 Object key = h.value().handleWeirdNumberValue(this, targetClass, value, msg);
967 if (key != DeserializationProblemHandler.NOT_HANDLED) {
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700968 // Sanity check for broken handlers, otherwise nasty to debug:
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -0700969 if (_isCompatible(targetClass, key)) {
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700970 return key;
971 }
Tatu Saloranta23a610d2017-07-26 16:57:29 -0700972 throw weirdNumberException(value, targetClass, _format(
Tatu Salorantad01e3ab2016-05-19 09:31:38 -0700973 "DeserializationProblemHandler.handleWeirdNumberValue() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700974 ClassUtil.getClassDescription(targetClass),
975 ClassUtil.getClassDescription(key)
976 ));
Tatu Saloranta888c6b92016-05-15 22:16:40 -0700977 }
978 h = h.next();
979 }
980 throw weirdNumberException(value, targetClass, msg);
981 }
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -0700982
Tatu Saloranta23a610d2017-07-26 16:57:29 -0700983 public Object handleWeirdNativeValue(JavaType targetType, Object badValue,
984 JsonParser p)
985 throws IOException
986 {
987 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
988 final Class<?> raw = targetType.getRawClass();
989 for (; h != null; h = h.next()) {
990 // Can bail out if it's handled
991 Object goodValue = h.value().handleWeirdNativeValue(this, targetType, badValue, p);
992 if (goodValue != DeserializationProblemHandler.NOT_HANDLED) {
993 // Sanity check for broken handlers, otherwise nasty to debug:
994 if ((goodValue == null) || raw.isInstance(goodValue)) {
995 return goodValue;
996 }
997 throw JsonMappingException.from(p, _format(
998"DeserializationProblemHandler.handleWeirdNativeValue() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -0700999 ClassUtil.getClassDescription(targetType),
1000 ClassUtil.getClassDescription(goodValue)
1001 ));
Tatu Saloranta23a610d2017-07-26 16:57:29 -07001002 }
1003 }
1004 throw weirdNativeValueException(badValue, raw);
1005 }
1006
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001007 /**
Tatu Saloranta68245442016-05-21 18:08:41 -07001008 * Method that deserializers should call if they fail to instantiate value
1009 * due to lack of viable instantiator (usually creator, that is, constructor
1010 * or static factory method). Method should be called at point where value
1011 * has not been decoded, so that handler has a chance to handle decoding
1012 * using alternate mechanism, and handle underlying content (possibly by
1013 * just skipping it) to keep input state valid
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001014 *
Tatu Saloranta68245442016-05-21 18:08:41 -07001015 * @param instClass Type that was to be instantiated
Tatu Salorantaed416862016-10-16 13:42:12 -07001016 * @param valueInst (optional) Value instantiator to be used, if any; null if type does not
1017 * use one for instantiation (custom deserialiers don't; standard POJO deserializer does)
Tatu Saloranta68245442016-05-21 18:08:41 -07001018 * @param p Parser that points to the JSON value to decode
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001019 *
Tatu Saloranta68245442016-05-21 18:08:41 -07001020 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001021 *
Tatu Salorantaed416862016-10-16 13:42:12 -07001022 * @since 2.9 (2.8 had alternate that did not take <code>ValueInstantiator</code>)
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001023 */
Tatu Salorantaed416862016-10-16 13:42:12 -07001024 @SuppressWarnings("resource")
1025 public Object handleMissingInstantiator(Class<?> instClass, ValueInstantiator valueInst,
1026 JsonParser p, String msg, Object... msgArgs)
Tatu Saloranta68245442016-05-21 18:08:41 -07001027 throws IOException
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001028 {
Tatu Salorantaed416862016-10-16 13:42:12 -07001029 if (p == null) {
1030 p = getParser();
1031 }
Tatu Saloranta79124862016-10-19 22:13:29 -07001032 msg = _format(msg, msgArgs);
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001033 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1034 while (h != null) {
1035 // Can bail out if it's handled
Tatu Saloranta68245442016-05-21 18:08:41 -07001036 Object instance = h.value().handleMissingInstantiator(this,
Tatu Salorantaed416862016-10-16 13:42:12 -07001037 instClass, valueInst, p, msg);
Tatu Saloranta68245442016-05-21 18:08:41 -07001038 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
1039 // Sanity check for broken handlers, otherwise nasty to debug:
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -07001040 if (_isCompatible(instClass, instance)) {
Tatu Saloranta68245442016-05-21 18:08:41 -07001041 return instance;
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001042 }
Tatu Saloranta816bbed2016-10-05 21:13:12 -07001043 reportBadDefinition(constructType(instClass), String.format(
1044"DeserializationProblemHandler.handleMissingInstantiator() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001045 ClassUtil.getClassDescription(instClass),
1046 ClassUtil.getClassDescription((instance)
1047 )));
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001048 }
1049 h = h.next();
1050 }
Tatu Salorantaed416862016-10-16 13:42:12 -07001051
1052 // 16-Oct-2016, tatu: This is either a definition problem (if no applicable creator
Tatu Saloranta581ba1f2017-01-25 21:55:11 -08001053 // exists), or input mismatch problem (otherwise) since none of existing creators
Tatu Salorantaed416862016-10-16 13:42:12 -07001054 // match with token.
1055 if ((valueInst != null) && !valueInst.canInstantiate()) {
Oliver Kopp68476802017-06-27 22:26:41 +03001056 msg = String.format("Cannot construct instance of %s (no Creators, like default construct, exist): %s",
Tatu Saloranta267abe12016-11-25 18:14:20 -08001057 ClassUtil.nameOf(instClass), msg);
Tatu Salorantaed416862016-10-16 13:42:12 -07001058 return reportBadDefinition(constructType(instClass), msg);
1059 }
Oliver Kopp68476802017-06-27 22:26:41 +03001060 msg = String.format("Cannot construct instance of %s (although at least one Creator exists): %s",
Tatu Saloranta267abe12016-11-25 18:14:20 -08001061 ClassUtil.nameOf(instClass), msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001062 return reportInputMismatch(instClass, msg);
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001063 }
1064
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001065 /**
1066 * Method that deserializers should call if they fail to instantiate value
1067 * due to an exception that was thrown by constructor (or other mechanism used
1068 * to create instances).
1069 * Default implementation will try to call {@link DeserializationProblemHandler#handleInstantiationProblem}
1070 * on configured handlers, if any, to allow for recovery; if recovery does not
1071 * succeed, will throw exception constructed with {@link #instantiationException}.
1072 *
1073 * @param instClass Type that was to be instantiated
1074 * @param argument (optional) Argument that was passed to constructor or equivalent
1075 * instantiator; often a {@link java.lang.String}.
1076 * @param t Exception that caused failure
1077 *
1078 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1079 *
1080 * @since 2.8
1081 */
1082 public Object handleInstantiationProblem(Class<?> instClass, Object argument,
1083 Throwable t)
1084 throws IOException
1085 {
1086 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1087 while (h != null) {
1088 // Can bail out if it's handled
Tatu Salorantad01e3ab2016-05-19 09:31:38 -07001089 Object instance = h.value().handleInstantiationProblem(this, instClass, argument, t);
1090 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
1091 // Sanity check for broken handlers, otherwise nasty to debug:
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -07001092 if (_isCompatible(instClass, instance)) {
Tatu Salorantad01e3ab2016-05-19 09:31:38 -07001093 return instance;
1094 }
Tatu Saloranta816bbed2016-10-05 21:13:12 -07001095 reportBadDefinition(constructType(instClass), String.format(
1096"DeserializationProblemHandler.handleInstantiationProblem() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001097 ClassUtil.getClassDescription(instClass),
1098 ClassUtil.classNameOf(instance)
1099 ));
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001100 }
1101 h = h.next();
1102 }
1103 // 18-May-2016, tatu: Only wrap if not already a valid type to throw
Tatu Saloranta78c72292016-11-07 20:37:45 -08001104 ClassUtil.throwIfIOE(t);
Tatu Salorantae3ec9dc2019-09-11 16:33:32 -07001105 // [databind#2164]: but see if wrapping is desired
1106 if (!isEnabled(DeserializationFeature.WRAP_EXCEPTIONS)) {
1107 ClassUtil.throwIfRTE(t);
1108 }
Tatu Saloranta609a0f82016-05-18 20:17:10 -07001109 throw instantiationException(instClass, t);
1110 }
1111
Tatu Saloranta68245442016-05-21 18:08:41 -07001112 /**
Tatu Saloranta851092c2016-05-21 20:08:40 -07001113 * Method that deserializers should call if the first token of the value to
1114 * deserialize is of unexpected type (that is, type of token that deserializer
Oliver Kopp5e3bf082017-06-27 14:12:19 +03001115 * cannot handle). This could occur, for example, if a Number deserializer
Tatu Saloranta851092c2016-05-21 20:08:40 -07001116 * encounter {@link JsonToken#START_ARRAY} instead of
1117 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1118 *
1119 * @param instClass Type that was to be instantiated
1120 * @param p Parser that points to the JSON value to decode
1121 *
1122 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1123 *
1124 * @since 2.8
1125 */
1126 public Object handleUnexpectedToken(Class<?> instClass, JsonParser p)
1127 throws IOException
1128 {
Tatu Saloranta2599caf2019-09-15 16:17:48 -07001129 return handleUnexpectedToken(constructType(instClass), p.getCurrentToken(), p, null);
Tatu Saloranta851092c2016-05-21 20:08:40 -07001130 }
Tatu Saloranta43fbd712016-11-09 21:43:27 -08001131
Tatu Saloranta851092c2016-05-21 20:08:40 -07001132 /**
1133 * Method that deserializers should call if the first token of the value to
1134 * deserialize is of unexpected type (that is, type of token that deserializer
Oliver Kopp5e3bf082017-06-27 14:12:19 +03001135 * cannot handle). This could occur, for example, if a Number deserializer
Tatu Saloranta851092c2016-05-21 20:08:40 -07001136 * encounter {@link JsonToken#START_ARRAY} instead of
1137 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1138 *
1139 * @param instClass Type that was to be instantiated
Tatu Saloranta2a877182016-10-15 18:18:22 -07001140 * @param t Token encountered that does match expected
Tatu Saloranta851092c2016-05-21 20:08:40 -07001141 * @param p Parser that points to the JSON value to decode
1142 *
1143 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1144 *
1145 * @since 2.8
1146 */
1147 public Object handleUnexpectedToken(Class<?> instClass, JsonToken t,
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001148 JsonParser p, String msg, Object... msgArgs)
Tatu Saloranta851092c2016-05-21 20:08:40 -07001149 throws IOException
1150 {
Semyon Levin28e775f2019-09-16 02:01:56 +03001151 return handleUnexpectedToken(constructType(instClass), t, p, msg, msgArgs);
1152 }
1153
1154 /**
1155 * Method that deserializers should call if the first token of the value to
1156 * deserialize is of unexpected type (that is, type of token that deserializer
1157 * cannot handle). This could occur, for example, if a Number deserializer
1158 * encounter {@link JsonToken#START_ARRAY} instead of
1159 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1160 *
1161 * @param targetType Type that was to be instantiated
1162 * @param p Parser that points to the JSON value to decode
1163 *
1164 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1165 *
1166 * @since 2.10
1167 */
1168 public Object handleUnexpectedToken(JavaType targetType, JsonParser p)
1169 throws IOException
1170 {
1171 return handleUnexpectedToken(targetType, p.getCurrentToken(), p, null);
1172 }
1173
1174 /**
1175 * Method that deserializers should call if the first token of the value to
1176 * deserialize is of unexpected type (that is, type of token that deserializer
1177 * cannot handle). This could occur, for example, if a Number deserializer
1178 * encounter {@link JsonToken#START_ARRAY} instead of
1179 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1180 *
1181 * @param targetType Type that was to be instantiated
1182 * @param t Token encountered that does match expected
1183 * @param p Parser that points to the JSON value to decode
1184 *
1185 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1186 *
1187 * @since 2.10
1188 */
1189 public Object handleUnexpectedToken(JavaType targetType, JsonToken t,
1190 JsonParser p, String msg, Object... msgArgs)
1191 throws IOException
1192 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001193 msg = _format(msg, msgArgs);
Tatu Saloranta851092c2016-05-21 20:08:40 -07001194 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1195 while (h != null) {
1196 Object instance = h.value().handleUnexpectedToken(this,
Semyon Levin28e775f2019-09-16 02:01:56 +03001197 targetType, t, p, msg);
Tatu Saloranta851092c2016-05-21 20:08:40 -07001198 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
Semyon Levin28e775f2019-09-16 02:01:56 +03001199 if (_isCompatible(targetType.getRawClass(), instance)) {
Tatu Saloranta851092c2016-05-21 20:08:40 -07001200 return instance;
1201 }
Semyon Levin28e775f2019-09-16 02:01:56 +03001202 reportBadDefinition(targetType, String.format(
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001203 "DeserializationProblemHandler.handleUnexpectedToken() for type %s returned value of type %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001204 ClassUtil.getClassDescription(targetType),
1205 ClassUtil.classNameOf(instance)
1206 ));
Tatu Saloranta851092c2016-05-21 20:08:40 -07001207 }
1208 h = h.next();
1209 }
Tatu Saloranta851092c2016-05-21 20:08:40 -07001210 if (msg == null) {
Tatu Saloranta73359ae2016-06-06 08:44:54 -07001211 if (t == null) {
1212 msg = String.format("Unexpected end-of-input when binding data into %s",
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001213 ClassUtil.getTypeDescription(targetType));
Tatu Saloranta73359ae2016-06-06 08:44:54 -07001214 } else {
Oliver Kopp68476802017-06-27 22:26:41 +03001215 msg = String.format("Cannot deserialize instance of %s out of %s token",
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001216 ClassUtil.getTypeDescription(targetType), t);
Tatu Saloranta73359ae2016-06-06 08:44:54 -07001217 }
Tatu Saloranta851092c2016-05-21 20:08:40 -07001218 }
Semyon Levin28e775f2019-09-16 02:01:56 +03001219 reportInputMismatch(targetType, msg);
Tatu Salorantaacc533a2016-05-22 21:47:18 -07001220 return null; // never gets here
Tatu Saloranta851092c2016-05-21 20:08:40 -07001221 }
1222
1223 /**
Tatu Saloranta68245442016-05-21 18:08:41 -07001224 * Method that deserializers should call if they encounter a type id
Oliver Kopp5e3bf082017-06-27 14:12:19 +03001225 * (for polymorphic deserialization) that cannot be resolved to an
Tatu Saloranta68245442016-05-21 18:08:41 -07001226 * actual type; usually since there is no mapping defined.
1227 * Default implementation will try to call {@link DeserializationProblemHandler#handleUnknownTypeId}
1228 * on configured handlers, if any, to allow for recovery; if recovery does not
Tatu Saloranta3ee81a62017-05-02 10:01:48 -07001229 * succeed, will throw exception constructed with {@link #invalidTypeIdException}.
Tatu Saloranta68245442016-05-21 18:08:41 -07001230 *
1231 * @param baseType Base type from which resolution starts
1232 * @param id Type id that could not be converted
1233 * @param extraDesc Additional problem description to add to default exception message,
1234 * if resolution fails.
1235 *
1236 * @return {@link JavaType} that id resolves to
1237 *
Oliver Kopp5e3bf082017-06-27 14:12:19 +03001238 * @throws IOException To indicate unrecoverable problem, if resolution cannot
Tatu Saloranta68245442016-05-21 18:08:41 -07001239 * be made to work
1240 *
1241 * @since 2.8
1242 */
1243 public JavaType handleUnknownTypeId(JavaType baseType, String id,
Tatu Salorantad6230fd2016-05-30 21:11:19 -07001244 TypeIdResolver idResolver, String extraDesc) throws IOException
Tatu Saloranta68245442016-05-21 18:08:41 -07001245 {
1246 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1247 while (h != null) {
1248 // Can bail out if it's handled
Tatu Salorantad6230fd2016-05-30 21:11:19 -07001249 JavaType type = h.value().handleUnknownTypeId(this, baseType, id, idResolver, extraDesc);
Tatu Saloranta68245442016-05-21 18:08:41 -07001250 if (type != null) {
1251 if (type.hasRawClass(Void.class)) {
1252 return null;
1253 }
1254 // But ensure there's type compatibility
1255 if (type.isTypeOrSubTypeOf(baseType.getRawClass())) {
1256 return type;
1257 }
Tatu Saloranta52238562017-04-28 10:52:23 -07001258 throw invalidTypeIdException(baseType, id,
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001259 "problem handler tried to resolve into non-subtype: "+
1260 ClassUtil.getTypeDescription(type));
Tatu Saloranta68245442016-05-21 18:08:41 -07001261 }
1262 h = h.next();
1263 }
Tatu Saloranta811ec172016-05-24 23:39:04 -07001264 // 24-May-2016, tatu: Actually we may still not want to fail quite yet
1265 if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
1266 return null;
1267 }
Tatu Saloranta52238562017-04-28 10:52:23 -07001268 throw invalidTypeIdException(baseType, id, extraDesc);
Tatu Saloranta68245442016-05-21 18:08:41 -07001269 }
1270
Tatu Saloranta5b8f0d92017-03-09 10:18:47 -08001271 /**
1272 * @since 2.9
1273 */
1274 public JavaType handleMissingTypeId(JavaType baseType,
1275 TypeIdResolver idResolver, String extraDesc) throws IOException
1276 {
1277 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1278 while (h != null) {
1279 // Can bail out if it's handled
1280 JavaType type = h.value().handleMissingTypeId(this, baseType, idResolver, extraDesc);
1281 if (type != null) {
1282 if (type.hasRawClass(Void.class)) {
1283 return null;
1284 }
1285 // But ensure there's type compatibility
1286 if (type.isTypeOrSubTypeOf(baseType.getRawClass())) {
1287 return type;
1288 }
Tatu Saloranta52238562017-04-28 10:52:23 -07001289 throw invalidTypeIdException(baseType, null,
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001290 "problem handler tried to resolve into non-subtype: "+
1291 ClassUtil.getTypeDescription(type));
Tatu Saloranta5b8f0d92017-03-09 10:18:47 -08001292 }
1293 h = h.next();
1294 }
1295 // 09-Mar-2017, tatu: We may want to consider yet another feature at some
1296 // point to allow returning `null`... but that seems bit risky for now
1297// if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
1298// return null;
1299// }
1300 throw missingTypeIdException(baseType, extraDesc);
1301 }
1302
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -07001303 /**
Tatu Saloranta9051c792019-08-20 20:12:34 -07001304 * Method that deserializer may call if it is called to do an update ("merge")
1305 * but deserializer operates on a non-mergeable type. Although this should
1306 * usually be caught earlier, sometimes it may only be caught during operation
1307 * and if so this is the method to call.
1308 * Note that if {@link MapperFeature#IGNORE_MERGE_FOR_UNMERGEABLE} is enabled,
1309 * this method will simply return null; otherwise {@link InvalidDefinitionException}
1310 * will be thrown.
1311 *
1312 * @since 2.10
1313 */
1314 public void handleBadMerge(JsonDeserializer<?> deser) throws JsonMappingException
1315 {
1316 if (!isEnabled(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)) {
1317 JavaType type = constructType(deser.handledType());
Tatu Salorantaa49faf92019-09-16 17:21:51 -07001318 String msg = String.format("Invalid configuration: values of type %s cannot be merged",
1319 ClassUtil.getTypeDescription(type));
Tatu Saloranta9051c792019-08-20 20:12:34 -07001320 throw InvalidDefinitionException.from(getParser(), msg, type);
1321 }
1322 }
1323
1324 /**
Tatu Salorantadcfb0cc2017-09-18 21:56:07 -07001325 * @since 2.9.2
1326 */
1327 protected boolean _isCompatible(Class<?> target, Object value)
1328 {
1329 if ((value == null) || target.isInstance(value)) {
1330 return true;
1331 }
1332 // [databind#1767]: Make sure to allow wrappers for primitive fields
1333 return target.isPrimitive()
1334 && ClassUtil.wrapperType(target).isInstance(value);
1335 }
1336
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001337 /*
1338 /**********************************************************
Tatu Saloranta68245442016-05-21 18:08:41 -07001339 /* Methods for problem reporting, in cases where recovery
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001340 /* is not considered possible: input problem
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001341 /**********************************************************
1342 */
1343
1344 /**
Tatu Saloranta68245442016-05-21 18:08:41 -07001345 * Method for deserializers to call
1346 * when the token encountered was of type different than what <b>should</b>
1347 * be seen at that position, usually within a sequence of expected tokens.
1348 * Note that this method will throw a {@link JsonMappingException} and no
1349 * recovery is attempted (via {@link DeserializationProblemHandler}, as
1350 * problem is considered to be difficult to recover from, in general.
1351 *
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001352 * @since 2.9
Tatu Saloranta68245442016-05-21 18:08:41 -07001353 */
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001354 public void reportWrongTokenException(JsonDeserializer<?> deser,
1355 JsonToken expToken, String msg, Object... msgArgs)
1356 throws JsonMappingException
1357 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001358 msg = _format(msg, msgArgs);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001359 throw wrongTokenException(getParser(), deser.handledType(), expToken, msg);
1360 }
1361
1362 /**
1363 * Method for deserializers to call
1364 * when the token encountered was of type different than what <b>should</b>
1365 * be seen at that position, usually within a sequence of expected tokens.
1366 * Note that this method will throw a {@link JsonMappingException} and no
1367 * recovery is attempted (via {@link DeserializationProblemHandler}, as
1368 * problem is considered to be difficult to recover from, in general.
1369 *
1370 * @since 2.9
1371 */
1372 public void reportWrongTokenException(JavaType targetType,
1373 JsonToken expToken, String msg, Object... msgArgs)
1374 throws JsonMappingException
1375 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001376 msg = _format(msg, msgArgs);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001377 throw wrongTokenException(getParser(), targetType, expToken, msg);
1378 }
1379
1380 /**
1381 * Method for deserializers to call
1382 * when the token encountered was of type different than what <b>should</b>
1383 * be seen at that position, usually within a sequence of expected tokens.
1384 * Note that this method will throw a {@link JsonMappingException} and no
1385 * recovery is attempted (via {@link DeserializationProblemHandler}, as
1386 * problem is considered to be difficult to recover from, in general.
1387 *
1388 * @since 2.9
1389 */
1390 public void reportWrongTokenException(Class<?> targetType,
1391 JsonToken expToken, String msg, Object... msgArgs)
1392 throws JsonMappingException
1393 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001394 msg = _format(msg, msgArgs);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001395 throw wrongTokenException(getParser(), targetType, expToken, msg);
1396 }
Tatu Saloranta9d1fb752016-06-07 22:47:04 -07001397
1398 /**
1399 * @since 2.8
1400 */
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001401 public <T> T reportUnresolvedObjectId(ObjectIdReader oidReader, Object bean)
Tatu Saloranta9d1fb752016-06-07 22:47:04 -07001402 throws JsonMappingException
1403 {
1404 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 -08001405 ClassUtil.classNameOf(bean), oidReader.propertyName);
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001406 return reportInputMismatch(oidReader.idProperty, msg);
Tatu Saloranta9d1fb752016-06-07 22:47:04 -07001407 }
1408
Tatu Salorantabb06aa02016-09-08 22:38:23 -07001409 /**
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001410 * Helper method used to indicate a problem with input in cases where more
1411 * specific <code>reportXxx()</code> method was not available.
1412 *
1413 * @since 2.9
1414 */
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001415 public <T> T reportInputMismatch(JsonDeserializer<?> src,
1416 String msg, Object... msgArgs) throws JsonMappingException
1417 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001418 msg = _format(msg, msgArgs);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001419 throw MismatchedInputException.from(getParser(), src.handledType(), msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001420 }
1421
1422 /**
1423 * Helper method used to indicate a problem with input in cases where more
1424 * specific <code>reportXxx()</code> method was not available.
1425 *
1426 * @since 2.9
1427 */
1428 public <T> T reportInputMismatch(Class<?> targetType,
1429 String msg, Object... msgArgs) throws JsonMappingException
1430 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001431 msg = _format(msg, msgArgs);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001432 throw MismatchedInputException.from(getParser(), targetType, msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001433 }
1434
1435 /**
1436 * Helper method used to indicate a problem with input in cases where more
1437 * specific <code>reportXxx()</code> method was not available.
1438 *
1439 * @since 2.9
1440 */
1441 public <T> T reportInputMismatch(JavaType targetType,
1442 String msg, Object... msgArgs) throws JsonMappingException
1443 {
Tatu Saloranta79124862016-10-19 22:13:29 -07001444 msg = _format(msg, msgArgs);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001445 throw MismatchedInputException.from(getParser(), targetType, msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001446 }
Tatu Salorantab8f60292016-10-25 22:50:06 -07001447
Tatu Salorantab3e41942019-09-11 14:18:02 -07001448 /**
1449 * Helper method used to indicate a problem with input in cases where more
1450 * specific <code>reportXxx()</code> method was not available.
1451 *
1452 * @since 2.9
1453 */
1454 public <T> T reportInputMismatch(BeanProperty prop,
1455 String msg, Object... msgArgs) throws JsonMappingException
1456 {
1457 msg = _format(msg, msgArgs);
1458 JavaType type = (prop == null) ? null : prop.getType();
1459 final MismatchedInputException e = MismatchedInputException.from(getParser(), type, msg);
1460 // [databind#2357]: Include property name, if we have it
1461 if (prop != null) {
1462 AnnotatedMember member = prop.getMember();
1463 if (member != null) {
1464 e.prependPath(member.getDeclaringClass(), prop.getName());
1465 }
1466 }
1467 throw e;
1468 }
1469
1470 /**
1471 * Helper method used to indicate a problem with input in cases where more
1472 * specific <code>reportXxx()</code> method was not available.
1473 *
1474 * @since 2.10
1475 */
1476 public <T> T reportPropertyInputMismatch(Class<?> targetType, String propertyName,
1477 String msg, Object... msgArgs) throws JsonMappingException
1478 {
1479 msg = _format(msg, msgArgs);
1480 MismatchedInputException e = MismatchedInputException.from(getParser(), targetType, msg);
1481 if (propertyName != null) {
1482 e.prependPath(targetType, propertyName);
1483 }
1484 throw e;
1485 }
1486
1487 /**
1488 * Helper method used to indicate a problem with input in cases where more
1489 * specific <code>reportXxx()</code> method was not available.
1490 *
1491 * @since 2.10
1492 */
1493 public <T> T reportPropertyInputMismatch(JavaType targetType, String propertyName,
1494 String msg, Object... msgArgs) throws JsonMappingException
1495 {
1496 return reportPropertyInputMismatch(targetType.getRawClass(), propertyName, msg, msgArgs);
1497 }
1498
Tatu Saloranta8f9226b2017-07-18 17:18:08 -07001499 public <T> T reportTrailingTokens(Class<?> targetType,
1500 JsonParser p, JsonToken trailingToken) throws JsonMappingException
1501 {
1502 throw MismatchedInputException.from(p, targetType, String.format(
1503"Trailing token (of type %s) found after value (bound as %s): not allowed as per `DeserializationFeature.FAIL_ON_TRAILING_TOKENS`",
1504trailingToken, ClassUtil.nameOf(targetType)
1505 ));
1506 }
1507
Tatu Salorantab8f60292016-10-25 22:50:06 -07001508 @Deprecated // since 2.9
1509 public void reportWrongTokenException(JsonParser p,
1510 JsonToken expToken, String msg, Object... msgArgs)
1511 throws JsonMappingException
1512 {
1513 msg = _format(msg, msgArgs);
1514 throw wrongTokenException(p, expToken, msg);
1515 }
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001516
Tatu Salorantab8f60292016-10-25 22:50:06 -07001517 /**
1518 * Helper method for reporting a problem with unhandled unknown property.
1519 *
1520 * @param instanceOrClass Either value being populated (if one has been
1521 * instantiated), or Class that indicates type that would be (or
1522 * have been) instantiated
1523 * @param deser Deserializer that had the problem, if called by deserializer
1524 * (or on behalf of one)
1525 *
1526 * @deprecated Since 2.8 call {@link #handleUnknownProperty} instead
1527 */
1528 @Deprecated
1529 public void reportUnknownProperty(Object instanceOrClass, String fieldName,
1530 JsonDeserializer<?> deser)
1531 throws JsonMappingException
1532 {
1533 if (isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
1534 // Do we know properties that are expected instead?
1535 Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames();
1536 throw UnrecognizedPropertyException.from(_parser,
1537 instanceOrClass, fieldName, propIds);
1538 }
1539 }
1540
1541 /**
1542 * @since 2.8
1543 *
1544 * @deprecated Since 2.9: not clear this ever occurs
1545 */
1546 @Deprecated // since 2.9
1547 public void reportMissingContent(String msg, Object... msgArgs) throws JsonMappingException {
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001548 throw MismatchedInputException.from(getParser(), (JavaType) null, "No content to map due to end-of-input");
Tatu Salorantab8f60292016-10-25 22:50:06 -07001549 }
1550
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001551 /*
1552 /**********************************************************
1553 /* Methods for problem reporting, in cases where recovery
1554 /* is not considered possible: POJO definition problems
1555 /**********************************************************
1556 */
1557
1558 /**
Tatu Salorantabb06aa02016-09-08 22:38:23 -07001559 * Helper method called to indicate problem in POJO (serialization) definitions or settings
1560 * regarding specific Java type, unrelated to actual JSON content to map.
1561 * Default behavior is to construct and throw a {@link JsonMappingException}.
1562 *
1563 * @since 2.9
1564 */
1565 public <T> T reportBadTypeDefinition(BeanDescription bean,
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001566 String msg, Object... msgArgs) throws JsonMappingException {
1567 msg = _format(msg, msgArgs);
Tatu Salorantae0889202017-03-30 15:43:20 -07001568 String beanDesc = ClassUtil.nameOf(bean.getBeanClass());
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001569 msg = String.format("Invalid type definition for type %s: %s", beanDesc, msg);
1570 throw InvalidDefinitionException.from(_parser, msg, bean, null);
Tatu Salorantabb06aa02016-09-08 22:38:23 -07001571 }
1572
1573 /**
1574 * Helper method called to indicate problem in POJO (serialization) definitions or settings
1575 * regarding specific property (of a type), unrelated to actual JSON content to map.
1576 * Default behavior is to construct and throw a {@link JsonMappingException}.
1577 *
1578 * @since 2.9
1579 */
1580 public <T> T reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop,
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001581 String msg, Object... msgArgs) throws JsonMappingException {
1582 msg = _format(msg, msgArgs);
Tatu Saloranta43fbd712016-11-09 21:43:27 -08001583 String propName = ClassUtil.nameOf(prop);
Tatu Salorantae0889202017-03-30 15:43:20 -07001584 String beanDesc = ClassUtil.nameOf(bean.getBeanClass());
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001585 msg = String.format("Invalid definition for property %s (of type %s): %s",
1586 propName, beanDesc, msg);
1587 throw InvalidDefinitionException.from(_parser, msg, bean, prop);
Tatu Salorantabb06aa02016-09-08 22:38:23 -07001588 }
1589
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001590 @Override
1591 public <T> T reportBadDefinition(JavaType type, String msg) throws JsonMappingException {
1592 throw InvalidDefinitionException.from(_parser, msg, type);
Tatu Saloranta851092c2016-05-21 20:08:40 -07001593 }
1594
Tatu Salorantab8f60292016-10-25 22:50:06 -07001595 /**
Tatu Saloranta9051c792019-08-20 20:12:34 -07001596 * @deprecated Since 2.10 use {@link #handleBadMerge} instead
Tatu Salorantab8f60292016-10-25 22:50:06 -07001597 */
Tatu Saloranta9051c792019-08-20 20:12:34 -07001598 @Deprecated // since 2.10
1599 public <T> T reportBadMerge(JsonDeserializer<?> deser) throws JsonMappingException {
1600 handleBadMerge(deser);
1601 return null;
Tatu Salorantab8f60292016-10-25 22:50:06 -07001602 }
1603
Tatu Saloranta2d318f62016-05-10 21:58:00 -07001604 /*
1605 /**********************************************************
1606 /* Methods for constructing semantic exceptions; usually not
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -07001607 /* to be called directly, call `handleXxx()` instead
Tatu Saloranta2d318f62016-05-10 21:58:00 -07001608 /**********************************************************
1609 */
1610
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001611 /**
Tatu Saloranta68245442016-05-21 18:08:41 -07001612 * Helper method for constructing {@link JsonMappingException} to indicate
Tatu Saloranta98dd0912016-05-15 23:13:44 -07001613 * that the token encountered was of type different than what <b>should</b>
1614 * be seen at that position, usually within a sequence of expected tokens.
1615 * Note that most of the time this method should NOT be directly called;
1616 * instead, {@link #reportWrongTokenException} should be called and will
1617 * call this method as necessary.
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001618 *
1619 * @since 2.9
Tatu Saloranta98dd0912016-05-15 23:13:44 -07001620 */
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001621 public JsonMappingException wrongTokenException(JsonParser p, JavaType targetType,
Tatu Saloranta79124862016-10-19 22:13:29 -07001622 JsonToken expToken, String extra)
Tatu Saloranta98dd0912016-05-15 23:13:44 -07001623 {
1624 String msg = String.format("Unexpected token (%s), expected %s",
1625 p.getCurrentToken(), expToken);
Tatu Saloranta79124862016-10-19 22:13:29 -07001626 msg = _colonConcat(msg, extra);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001627 return MismatchedInputException.from(p, targetType, msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001628 }
1629
1630 public JsonMappingException wrongTokenException(JsonParser p, Class<?> targetType,
Tatu Saloranta79124862016-10-19 22:13:29 -07001631 JsonToken expToken, String extra)
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001632 {
1633 String msg = String.format("Unexpected token (%s), expected %s",
1634 p.getCurrentToken(), expToken);
Tatu Saloranta79124862016-10-19 22:13:29 -07001635 msg = _colonConcat(msg, extra);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001636 return MismatchedInputException.from(p, targetType, msg);
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001637 }
1638
1639 @Deprecated // since 2.9
1640 public JsonMappingException wrongTokenException(JsonParser p, JsonToken expToken,
1641 String msg)
1642 {
1643 return wrongTokenException(p, (JavaType) null, expToken, msg);
Tatu Saloranta98dd0912016-05-15 23:13:44 -07001644 }
1645
1646 /**
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001647 * Helper method for constructing exception to indicate that given JSON
1648 * Object field name was not in format to be able to deserialize specified
1649 * key type.
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001650 * Note that most of the time this method should NOT be called; instead,
1651 * {@link #handleWeirdKey} should be called which will call this method
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -07001652 * if necessary.
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001653 */
1654 public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue,
1655 String msg) {
1656 return InvalidFormatException.from(_parser,
Oliver Kopp68476802017-06-27 22:26:41 +03001657 String.format("Cannot deserialize Map key of type %s from String %s: %s",
Tatu Saloranta267abe12016-11-25 18:14:20 -08001658 ClassUtil.nameOf(keyClass), _quotedString(keyValue), msg),
Tatu Saloranta1e5fd122016-05-09 23:26:30 -07001659 keyValue, keyClass);
1660 }
1661
Tatu Saloranta2d318f62016-05-10 21:58:00 -07001662 /**
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001663 * Helper method for constructing exception to indicate that input JSON
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -07001664 * String was not suitable for deserializing into given target type.
1665 * Note that most of the time this method should NOT be called; instead,
1666 * {@link #handleWeirdStringValue} should be called which will call this method
1667 * if necessary.
1668 *
1669 * @param value String value from input being deserialized
1670 * @param instClass Type that String should be deserialized into
Tatu Saloranta94c56eb2019-01-18 20:45:25 -08001671 * @param msgBase Message that describes specific problem
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -07001672 *
1673 * @since 2.1
1674 */
1675 public JsonMappingException weirdStringException(String value, Class<?> instClass,
Tatu Saloranta94c56eb2019-01-18 20:45:25 -08001676 String msgBase) {
1677 final String msg = String.format("Cannot deserialize value of type %s from String %s: %s",
1678 ClassUtil.nameOf(instClass), _quotedString(value), msgBase);
1679 return InvalidFormatException.from(_parser, msg, value, instClass);
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -07001680 }
1681
1682 /**
1683 * Helper method for constructing exception to indicate that input JSON
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001684 * Number was not suitable for deserializing into given target type.
Tatu Saloranta0b6cb9b2016-05-15 22:59:17 -07001685 * Note that most of the time this method should NOT be called; instead,
1686 * {@link #handleWeirdNumberValue} should be called which will call this method
1687 * if necessary.
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001688 */
1689 public JsonMappingException weirdNumberException(Number value, Class<?> instClass,
1690 String msg) {
1691 return InvalidFormatException.from(_parser,
Oliver Kopp68476802017-06-27 22:26:41 +03001692 String.format("Cannot deserialize value of type %s from number %s: %s",
Tatu Saloranta267abe12016-11-25 18:14:20 -08001693 ClassUtil.nameOf(instClass), String.valueOf(value), msg),
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001694 value, instClass);
1695 }
Tatu Salorantab1041d02016-05-19 08:22:50 -07001696
1697 /**
Tatu Saloranta23a610d2017-07-26 16:57:29 -07001698 * Helper method for constructing exception to indicate that input JSON
1699 * token of type "native value" (see {@link JsonToken#VALUE_EMBEDDED_OBJECT})
1700 * is of incompatible type (and there is no delegating creator or such to use)
1701 * and can not be used to construct value of specified type (usually POJO).
1702 * Note that most of the time this method should NOT be called; instead,
1703 * {@link #handleWeirdNativeValue} should be called which will call this method
1704 *
1705 * @since 2.9
1706 */
1707 public JsonMappingException weirdNativeValueException(Object value, Class<?> instClass)
1708 {
1709 return InvalidFormatException.from(_parser, String.format(
1710"Cannot deserialize value of type %s from native value (`JsonToken.VALUE_EMBEDDED_OBJECT`) of type %s: incompatible types",
1711 ClassUtil.nameOf(instClass), ClassUtil.classNameOf(value)),
1712 value, instClass);
1713 }
1714
1715 /**
Tatu Salorantab1041d02016-05-19 08:22:50 -07001716 * Helper method for constructing instantiation exception for specified type,
1717 * to indicate problem with physically constructing instance of
1718 * specified class (missing constructor, exception from constructor)
1719 *<p>
Tatu Saloranta555cbeb2018-08-28 22:19:01 -07001720 * Note that most of the time this method should NOT be called directly; instead,
Tatu Salorantab1041d02016-05-19 08:22:50 -07001721 * {@link #handleInstantiationProblem} should be called which will call this method
1722 * if necessary.
1723 */
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001724 public JsonMappingException instantiationException(Class<?> instClass, Throwable cause) {
Tatu Saloranta555cbeb2018-08-28 22:19:01 -07001725 String excMsg;
1726 if (cause == null) {
1727 excMsg = "N/A";
Tatu Salorantaf6cf1812018-09-05 23:17:05 -07001728 } else if ((excMsg = ClassUtil.exceptionMessage(cause)) == null) {
Tatu Saloranta555cbeb2018-08-28 22:19:01 -07001729 excMsg = ClassUtil.nameOf(cause.getClass());
1730 }
Oliver Kopp68476802017-06-27 22:26:41 +03001731 String msg = String.format("Cannot construct instance of %s, problem: %s",
Tatu Saloranta555cbeb2018-08-28 22:19:01 -07001732 ClassUtil.nameOf(instClass), excMsg);
Tatu Saloranta39294f92018-09-04 22:25:50 -07001733 // [databind#2162]: use specific exception type as we don't know if it's
1734 // due to type definition, input, or neither
1735 return ValueInstantiationException.from(_parser, msg, constructType(instClass), cause);
Tatu Salorantab1041d02016-05-19 08:22:50 -07001736 }
1737
Tatu Saloranta888c6b92016-05-15 22:16:40 -07001738 /**
Tatu Saloranta68245442016-05-21 18:08:41 -07001739 * Helper method for constructing instantiation exception for specified type,
1740 * to indicate that instantiation failed due to missing instantiator
1741 * (creator; constructor or factory method).
1742 *<p>
1743 * Note that most of the time this method should NOT be called; instead,
1744 * {@link #handleMissingInstantiator} should be called which will call this method
1745 * if necessary.
1746 */
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001747 public JsonMappingException instantiationException(Class<?> instClass, String msg0) {
Tatu Saloranta39294f92018-09-04 22:25:50 -07001748 // [databind#2162]: use specific exception type as we don't know if it's
1749 // due to type definition, input, or neither
1750 return ValueInstantiationException.from(_parser,
1751 String.format("Cannot construct instance of %s: %s",
1752 ClassUtil.nameOf(instClass), msg0),
1753 constructType(instClass));
Tatu Saloranta68245442016-05-21 18:08:41 -07001754 }
1755
Tatu Saloranta3e75d542017-05-02 22:45:54 -07001756 @Override
Tatu Saloranta52238562017-04-28 10:52:23 -07001757 public JsonMappingException invalidTypeIdException(JavaType baseType, String typeId,
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -07001758 String extraDesc) {
Tatu Saloranta52238562017-04-28 10:52:23 -07001759 String msg = String.format("Could not resolve type id '%s' as a subtype of %s",
Tatu Saloranta5f1bb5a2019-11-04 22:05:23 -08001760 typeId, ClassUtil.getTypeDescription(baseType));
Tatu Saloranta125ac182017-03-09 11:10:02 -08001761 return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, typeId);
Tatu Saloranta2d318f62016-05-10 21:58:00 -07001762 }
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -07001763
Tatu Saloranta5b8f0d92017-03-09 10:18:47 -08001764 /**
1765 * @since 2.9
1766 */
1767 public JsonMappingException missingTypeIdException(JavaType baseType,
1768 String extraDesc) {
1769 String msg = String.format("Missing type id when trying to resolve subtype of %s",
1770 baseType);
Tatu Saloranta125ac182017-03-09 11:10:02 -08001771 return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, null);
Tatu Saloranta5b8f0d92017-03-09 10:18:47 -08001772 }
1773
Tatu Saloranta34eaa4f2016-05-05 13:11:44 -07001774 /*
1775 /**********************************************************
Tatu Saloranta851092c2016-05-21 20:08:40 -07001776 /* Deprecated exception factory methods
Tatu Saloranta34eaa4f2016-05-05 13:11:44 -07001777 /**********************************************************
1778 */
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001779
Tatu Saloranta7a4193f2016-05-05 12:55:05 -07001780 /**
Tatu Saloranta7fc32382014-12-26 17:19:09 -08001781 * @since 2.5
Tatu Saloranta2ffca932016-05-05 12:23:14 -07001782 *
Tatu Saloranta33ba4ad2016-05-10 20:03:26 -07001783 * @deprecated Since 2.8 use {@link #handleUnknownTypeId} instead
Tatu Saloranta7fc32382014-12-26 17:19:09 -08001784 */
Tatu Saloranta2ffca932016-05-05 12:23:14 -07001785 @Deprecated
Tatu Saloranta7fc32382014-12-26 17:19:09 -08001786 public JsonMappingException unknownTypeException(JavaType type, String id,
Tatu Saloranta43fbd712016-11-09 21:43:27 -08001787 String extraDesc)
1788 {
Tatu Saloranta8c3eb032016-04-20 22:52:38 -07001789 String msg = String.format("Could not resolve type id '%s' into a subtype of %s",
Tatu Saloranta5f1bb5a2019-11-04 22:05:23 -08001790 id, ClassUtil.getTypeDescription(type));
Tatu Saloranta79124862016-10-19 22:13:29 -07001791 msg = _colonConcat(msg, extraDesc);
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001792 return MismatchedInputException.from(_parser, type, msg);
Tatu Saloranta7fc32382014-12-26 17:19:09 -08001793 }
1794
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -07001795 /**
1796 * Helper method for constructing exception to indicate that end-of-input was
1797 * reached while still expecting more tokens to deserialize value of specified type.
1798 *
1799 * @deprecated Since 2.8; currently no way to catch EOF at databind level
1800 */
1801 @Deprecated
1802 public JsonMappingException endOfInputException(Class<?> instClass) {
Tatu Salorantaa0bd1592016-11-25 18:49:52 -08001803 return MismatchedInputException.from(_parser, instClass,
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001804 "Unexpected end-of-input when trying to deserialize a "+instClass.getName());
Tatu Saloranta1ecc6b52016-05-10 22:18:53 -07001805 }
1806
Tatu Saloranta06c20b12012-01-29 21:36:52 -08001807 /*
1808 /**********************************************************
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001809 /* Deprecated methods for constructing, throwing non-specific
1810 /* JsonMappingExceptions: as of 2.9, should use more specific
1811 /* ones.
1812 /**********************************************************
1813 */
1814
1815 /**
1816 * Fallback method that may be called if no other <code>reportXxx</code>
1817 * is applicable -- but only in that case.
1818 *
1819 * @since 2.8
1820 *
Tatu Salorantad9b0cae2017-04-24 22:49:03 -07001821 * @deprecated Since 2.9: use a more specific method, or {@link #reportBadDefinition(JavaType, String)},
Tatu Salorantafbc1fa22016-10-06 15:07:52 -07001822 * or {@link #reportInputMismatch} instead
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001823 */
1824 @Deprecated // since 2.9
1825 public void reportMappingException(String msg, Object... msgArgs)
1826 throws JsonMappingException
1827 {
Tatu Salorantae27ec2d2016-10-24 22:44:16 -07001828 throw JsonMappingException.from(getParser(), _format(msg, msgArgs));
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001829 }
1830
1831 /**
1832 * Helper method for constructing generic mapping exception with specified
1833 * message and current location information.
1834 * Note that application code should almost always call
1835 * one of <code>handleXxx</code> methods, or {@link #reportMappingException(String, Object...)}
1836 * instead.
1837 *
1838 * @since 2.6
1839 *
1840 * @deprecated Since 2.9 use more specific error reporting methods instead
1841 */
1842 @Deprecated
1843 public JsonMappingException mappingException(String message) {
1844 return JsonMappingException.from(getParser(), message);
1845 }
1846
1847 /**
1848 * Helper method for constructing generic mapping exception with specified
1849 * message and current location information
1850 * Note that application code should almost always call
1851 * one of <code>handleXxx</code> methods, or {@link #reportMappingException(String, Object...)}
1852 * instead.
1853 *
1854 * @since 2.6
1855 *
1856 * @deprecated Since 2.9 use more specific error reporting methods instead
1857 */
1858 @Deprecated
Tatu Saloranta4fc0fb32016-10-20 23:04:31 -07001859 public JsonMappingException mappingException(String msg, Object... msgArgs) {
1860 return JsonMappingException.from(getParser(), _format(msg, msgArgs));
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001861 }
1862
1863 /**
1864 * Helper method for constructing generic mapping exception for specified type
1865 *
1866 * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
1867 */
1868 @Deprecated
1869 public JsonMappingException mappingException(Class<?> targetClass) {
1870 return mappingException(targetClass, _parser.getCurrentToken());
1871 }
1872
1873 /**
1874 * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
1875 */
1876 @Deprecated
1877 public JsonMappingException mappingException(Class<?> targetClass, JsonToken token) {
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001878 return JsonMappingException.from(_parser,
Oliver Kopp68476802017-06-27 22:26:41 +03001879 String.format("Cannot deserialize instance of %s out of %s token",
Tatu Saloranta9a81cf12017-09-18 22:04:55 -07001880 ClassUtil.nameOf(targetClass), token));
Tatu Salorantac1478ac2016-09-29 08:17:03 -07001881 }
1882
1883 /*
1884 /**********************************************************
Tatu Saloranta851092c2016-05-21 20:08:40 -07001885 /* Other internal methods
Tatu Saloranta06c20b12012-01-29 21:36:52 -08001886 /**********************************************************
1887 */
1888
1889 protected DateFormat getDateFormat()
1890 {
Tatu Saloranta3b88a6b2012-02-24 09:53:59 -08001891 if (_dateFormat != null) {
1892 return _dateFormat;
Tatu Saloranta06c20b12012-01-29 21:36:52 -08001893 }
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -08001894 /* 24-Feb-2012, tatu: At this point, all timezone configuration
Cowtowncoder8d0d6e42015-01-22 15:36:13 -08001895 * should have occurred, with respect to default dateformat
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -08001896 * and timezone configuration. But we still better clone
1897 * an instance as formatters may be stateful.
Tatu Saloranta3b88a6b2012-02-24 09:53:59 -08001898 */
1899 DateFormat df = _config.getDateFormat();
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -08001900 _dateFormat = df = (DateFormat) df.clone();
Tatu Saloranta3b88a6b2012-02-24 09:53:59 -08001901 return df;
Tatu Saloranta06c20b12012-01-29 21:36:52 -08001902 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001903}