1 package com.fasterxml.jackson.databind;
2
3 import java.io.IOException;
4 import java.text.DateFormat;
5 import java.text.ParseException;
6 import java.util.*;
7 import java.util.concurrent.atomic.AtomicReference;
8
9 import com.fasterxml.jackson.annotation.JsonFormat;
10 import com.fasterxml.jackson.annotation.ObjectIdGenerator;
11 import com.fasterxml.jackson.annotation.ObjectIdResolver;
12
13 import com.fasterxml.jackson.core.*;
14
15 import com.fasterxml.jackson.databind.cfg.ContextAttributes;
16 import com.fasterxml.jackson.databind.deser.*;
17 import com.fasterxml.jackson.databind.deser.impl.ObjectIdReader;
18 import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
19 import com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer;
20 import com.fasterxml.jackson.databind.exc.MismatchedInputException;
21 import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
22 import com.fasterxml.jackson.databind.exc.InvalidFormatException;
23 import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
24 import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
25 import com.fasterxml.jackson.databind.exc.ValueInstantiationException;
26 import com.fasterxml.jackson.databind.introspect.Annotated;
27 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
28 import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
29 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
30 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
31 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
32 import com.fasterxml.jackson.databind.type.TypeFactory;
33 import com.fasterxml.jackson.databind.util.*;
34
35 /**
36 * 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).
39 *<p>
40 * Instance life-cycle is such that a partially configured "blueprint" object
41 * is registered with {@link ObjectMapper} (and {@link ObjectReader},
42 * 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
45 * ({@link com.fasterxml.jackson.databind.deser.DefaultDeserializationContext#createInstance}).
46 * Each instance is guaranteed to only be used from single-threaded context;
47 * instances may be reused if (and only if) no configuration has changed.
48 *<p>
49 * Defined as abstract class so that implementations must define methods
50 * for reconfiguring blueprints and creating instances.
51 */
52 public abstract class DeserializationContext
53 extends DatabindContext
54 implements java.io.Serializable
55 {
56 private static final long serialVersionUID = 1L; // 2.6
57
58 /*
59 /**********************************************************
60 /* Configuration, immutable
61 /**********************************************************
62 */
63
64 /**
65 * Object that handle details of {@link JsonDeserializer} caching.
66 */
67 protected final DeserializerCache _cache;
68
69 /*
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 */
80 protected final DeserializerFactory _factory;
81
82 /*
83 /**********************************************************
84 /* Configuration that gets set for instances (not blueprints)
85 /* (partly denormalized for performance)
86 /**********************************************************
87 */
88
89 /**
90 * Generic deserialization processing configuration
91 */
92 protected final DeserializationConfig _config;
93
94 /**
95 * Bitmap of {@link DeserializationFeature}s that are enabled
96 */
97 protected final int _featureFlags;
98
99 /**
100 * Currently active view, if any.
101 */
102 protected final Class<?> _view;
103
104 /**
105 * Currently active parser used for deserialization.
106 * May be different from the outermost parser
107 * when content is buffered.
108 */
109 protected transient JsonParser _parser;
110
111 /**
112 * Object used for resolving references to injectable
113 * values.
114 */
115 protected final InjectableValues _injectableValues;
116
117 /*
118 /**********************************************************
119 /* Per-operation reusable helper objects (not for blueprints)
120 /**********************************************************
121 */
122
123 protected transient ArrayBuilders _arrayBuilders;
124
125 protected transient ObjectBuffer _objectBuffer;
126
127 protected transient DateFormat _dateFormat;
128
129 /**
130 * Lazily-constructed holder for per-call attributes.
131 *
132 * @since 2.3
133 */
134 protected transient ContextAttributes _attributes;
135
136 /**
137 * Type of {@link JsonDeserializer} (or, more specifically,
138 * {@link ContextualDeserializer}) that is being
139 * contextualized currently.
140 *
141 * @since 2.5
142 */
143 protected LinkedNode<JavaType> _currentType;
144
145 /*
146 /**********************************************************
147 /* Life-cycle
148 /**********************************************************
149 */
150
151 protected DeserializationContext(DeserializerFactory df) {
152 this(df, null);
153 }
154
155 protected DeserializationContext(DeserializerFactory df,
156 DeserializerCache cache)
157 {
158 if (df == null) {
159 throw new NullPointerException("Cannot pass null DeserializerFactory");
160 }
161 _factory = df;
162 if (cache == null) {
163 cache = new DeserializerCache();
164 }
165 _cache = cache;
166 _featureFlags = 0;
167 _config = null;
168 _injectableValues = null;
169 _view = null;
170 _attributes = null;
171 }
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;
184 _attributes = src._attributes;
185 }
186
187 /**
188 * Constructor used for creating actual per-call instances.
189 */
190 protected DeserializationContext(DeserializationContext src,
191 DeserializationConfig config, JsonParser p,
192 InjectableValues injectableValues)
193 {
194 _cache = src._cache;
195 _factory = src._factory;
196
197 _config = config;
198 _featureFlags = config.getDeserializationFeatures();
199 _view = config.getActiveView();
200 _parser = p;
201 _injectableValues = injectableValues;
202 _attributes = config.getAttributes();
203 }
204
205 /**
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
218 /*
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
231 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 }
244
245 @Override
246 public final AnnotationIntrospector getAnnotationIntrospector() {
247 return _config.getAnnotationIntrospector();
248 }
249
250 @Override
251 public final TypeFactory getTypeFactory() {
252 return _config.getTypeFactory();
253 }
254
255 @Override // since 2.11
256 public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
257 throws IllegalArgumentException
258 {
259 if (baseType.hasRawClass(subclass)) {
260 return baseType;
261 }
262 // On deserialization side, still uses "strict" type-compatibility checking;
263 // see [databind#2632] about serialization side
264 return getConfig().getTypeFactory().constructSpecializedType(baseType, subclass, false);
265 }
266
267 /**
268 * Method for accessing default Locale to use: convenience method for
269 *<pre>
270 * getConfig().getLocale();
271 *</pre>
272 */
273 @Override
274 public Locale getLocale() {
275 return _config.getLocale();
276 }
277
278 /**
279 * Method for accessing default TimeZone to use: convenience method for
280 *<pre>
281 * getConfig().getTimeZone();
282 *</pre>
283 */
284 @Override
285 public TimeZone getTimeZone() {
286 return _config.getTimeZone();
287 }
288
289 /*
290 /**********************************************************
291 /* Access to per-call state, like generic attributes (2.3+)
292 /**********************************************************
293 */
294
295 @Override
296 public Object getAttribute(Object key) {
297 return _attributes.getAttribute(key);
298 }
299
300 @Override
301 public DeserializationContext setAttribute(Object key, Object value)
302 {
303 _attributes = _attributes.withPerCallAttribute(key, value);
304 return this;
305 }
306
307 /**
308 * Accessor to {@link JavaType} of currently contextualized
309 * {@link ContextualDeserializer}, if any.
310 * This is sometimes useful for generic {@link JsonDeserializer}s that
311 * do not get passed (or do not retain) type information when being
312 * constructed: happens for example for deserializers constructed
313 * from annotations.
314 *
315 * @since 2.5
316 *
317 * @return Type of {@link ContextualDeserializer} being contextualized,
318 * if process is on-going; null if not.
319 */
320 public JavaType getContextualType() {
321 return (_currentType == null) ? null : _currentType.value();
322 }
323
324 /*
325 /**********************************************************
326 /* Public API, config setting accessors
327 /**********************************************************
328 */
329
330 /**
331 * Method for getting current {@link DeserializerFactory}.
332 */
333 public DeserializerFactory getFactory() {
334 return _factory;
335 }
336
337 /**
338 * Convenience method for checking whether specified on/off
339 * feature is enabled
340 */
341 public final boolean isEnabled(DeserializationFeature feat) {
342 /* 03-Dec-2010, tatu: minor shortcut; since this is called quite often,
343 * let's use a local copy of feature settings:
344 */
345 return (_featureFlags & feat.getMask()) != 0;
346 }
347
348 /**
349 * Bulk access method for getting the bit mask of all {@link DeserializationFeature}s
350 * that are enabled.
351 *
352 * @since 2.6
353 */
354 public final int getDeserializationFeatures() {
355 return _featureFlags;
356 }
357
358 /**
359 * Bulk access method for checking that all features specified by
360 * mask are enabled.
361 *
362 * @since 2.3
363 */
364 public final boolean hasDeserializationFeatures(int featureMask) {
365 return (_featureFlags & featureMask) == featureMask;
366 }
367
368 /**
369 * Bulk access method for checking that at least one of features specified by
370 * mask is enabled.
371 *
372 * @since 2.6
373 */
374 public final boolean hasSomeOfFeatures(int featureMask) {
375 return (_featureFlags & featureMask) != 0;
376 }
377
378 /**
379 * Method for accessing the currently active parser.
380 * May be different from the outermost parser
381 * when content is buffered.
382 *<p>
383 * Use of this method is discouraged: if code has direct access
384 * to the active parser, that should be used instead.
385 */
386 public final JsonParser getParser() { return _parser; }
387
388 public final Object findInjectableValue(Object valueId,
389 BeanProperty forProperty, Object beanInstance)
390 throws JsonMappingException
391 {
392 if (_injectableValues == null) {
393 reportBadDefinition(ClassUtil.classOf(valueId), String.format(
394 "No 'injectableValues' configured, cannot inject value with id [%s]", valueId));
395 }
396 return _injectableValues.findInjectableValue(valueId, this, forProperty, beanInstance);
397 }
398
399 /**
400 * Convenience method for accessing the default Base64 encoding
401 * used for decoding base64 encoded binary content.
402 * Same as calling:
403 *<pre>
404 * getConfig().getBase64Variant();
405 *</pre>
406 */
407 public final Base64Variant getBase64Variant() {
408 return _config.getBase64Variant();
409 }
410
411 /**
412 * Convenience method, functionally equivalent to:
413 *<pre>
414 * getConfig().getNodeFactory();
415 * </pre>
416 */
417 public final JsonNodeFactory getNodeFactory() {
418 return _config.getNodeFactory();
419 }
420
421 /*
422 /**********************************************************
423 /* Public API, pass-through to DeserializerCache
424 /**********************************************************
425 */
426
427 /**
428 * Method for checking whether we could find a deserializer
429 * for given type.
430 *
431 * @param type
432 * @since 2.3
433 */
434 public boolean hasValueDeserializerFor(JavaType type, AtomicReference<Throwable> cause) {
435 try {
436 return _cache.hasValueDeserializerFor(this, _factory, type);
437 } catch (JsonMappingException e) {
438 if (cause != null) {
439 cause.set(e);
440 }
441 } catch (RuntimeException e) {
442 if (cause == null) { // earlier behavior
443 throw e;
444 }
445 cause.set(e);
446 }
447 return false;
448 }
449
450 /**
451 * Method for finding a value deserializer, and creating a contextual
452 * version if necessary, for value reached via specified property.
453 */
454 @SuppressWarnings("unchecked")
455 public final JsonDeserializer<Object> findContextualValueDeserializer(JavaType type,
456 BeanProperty prop) throws JsonMappingException
457 {
458 JsonDeserializer<Object> deser = _cache.findValueDeserializer(this, _factory, type);
459 if (deser != null) {
460 deser = (JsonDeserializer<Object>) handleSecondaryContextualization(deser, prop, type);
461 }
462 return deser;
463 }
464
465 /**
466 * Variant that will try to locate deserializer for current type, but without
467 * performing any contextualization (unlike {@link #findContextualValueDeserializer})
468 * or checking for need to create a {@link TypeDeserializer} (unlike
469 * {@link #findRootValueDeserializer(JavaType)}.
470 * This method is usually called from within {@link ResolvableDeserializer#resolve},
471 * and expectation is that caller then calls either
472 * {@link #handlePrimaryContextualization(JsonDeserializer, BeanProperty, JavaType)} or
473 * {@link #handleSecondaryContextualization(JsonDeserializer, BeanProperty, JavaType)} at a
474 * later point, as necessary.
475 *
476 * @since 2.5
477 */
478 public final JsonDeserializer<Object> findNonContextualValueDeserializer(JavaType type)
479 throws JsonMappingException
480 {
481 return _cache.findValueDeserializer(this, _factory, type);
482 }
483
484 /**
485 * Method for finding a deserializer for root-level value.
486 */
487 @SuppressWarnings("unchecked")
488 public final JsonDeserializer<Object> findRootValueDeserializer(JavaType type)
489 throws JsonMappingException
490 {
491 JsonDeserializer<Object> deser = _cache.findValueDeserializer(this,
492 _factory, type);
493 if (deser == null) { // can this occur?
494 return null;
495 }
496 deser = (JsonDeserializer<Object>) handleSecondaryContextualization(deser, null, type);
497 TypeDeserializer typeDeser = _factory.findTypeDeserializer(_config, type);
498 if (typeDeser != null) {
499 // important: contextualize to indicate this is for root value
500 typeDeser = typeDeser.forProperty(null);
501 return new TypeWrappedDeserializer(typeDeser, deser);
502 }
503 return deser;
504 }
505
506 /**
507 * Convenience method, functionally same as:
508 *<pre>
509 * getDeserializerProvider().findKeyDeserializer(getConfig(), prop.getType(), prop);
510 *</pre>
511 */
512 public final KeyDeserializer findKeyDeserializer(JavaType keyType,
513 BeanProperty prop) throws JsonMappingException {
514 KeyDeserializer kd = _cache.findKeyDeserializer(this,
515 _factory, keyType);
516 // Second: contextualize?
517 if (kd instanceof ContextualKeyDeserializer) {
518 kd = ((ContextualKeyDeserializer) kd).createContextual(this, prop);
519 }
520 return kd;
521 }
522
523 /*
524 /**********************************************************
525 /* Public API, ObjectId handling
526 /**********************************************************
527 */
528
529 /**
530 * Method called to find and return entry corresponding to given
531 * Object Id: will add an entry if necessary, and never returns null
532 */
533 public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> generator, ObjectIdResolver resolver);
534
535 /**
536 * Method called to ensure that every object id encounter during processing
537 * are resolved.
538 *
539 * @throws UnresolvedForwardReference
540 */
541 public abstract void checkUnresolvedObjectId()
542 throws UnresolvedForwardReference;
543
544 /*
545 /**********************************************************
546 /* Public API, type handling
547 /**********************************************************
548 */
549
550 /**
551 * Convenience method, functionally equivalent to:
552 *<pre>
553 * getConfig().constructType(cls);
554 * </pre>
555 */
556 public final JavaType constructType(Class<?> cls) {
557 return (cls == null) ? null : _config.constructType(cls);
558 }
559
560 /**
561 * Helper method that is to be used when resolving basic class name into
562 * Class instance, the reason being that it may be necessary to work around
563 * various ClassLoader limitations, as well as to handle primitive type
564 * signatures.
565 *
566 * @since 2.6
567 */
568 public Class<?> findClass(String className) throws ClassNotFoundException
569 {
570 // By default, delegate to ClassUtil: can be overridden with custom handling
571 return getTypeFactory().findClass(className);
572 }
573
574 /*
575 /**********************************************************
576 /* Public API, helper object recycling
577 /**********************************************************
578 */
579
580 /**
581 * Method that can be used to get access to a reusable ObjectBuffer,
582 * useful for efficiently constructing Object arrays and Lists.
583 * Note that leased buffers should be returned once deserializer
584 * is done, to allow for reuse during same round of deserialization.
585 */
586 public final ObjectBuffer leaseObjectBuffer()
587 {
588 ObjectBuffer buf = _objectBuffer;
589 if (buf == null) {
590 buf = new ObjectBuffer();
591 } else {
592 _objectBuffer = null;
593 }
594 return buf;
595 }
596
597 /**
598 * Method to call to return object buffer previously leased with
599 * {@link #leaseObjectBuffer}.
600 *
601 * @param buf Returned object buffer
602 */
603 public final void returnObjectBuffer(ObjectBuffer buf)
604 {
605 /* Already have a reusable buffer? Let's retain bigger one
606 * (or if equal, favor newer one, shorter life-cycle)
607 */
608 if (_objectBuffer == null
609 || buf.initialCapacity() >= _objectBuffer.initialCapacity()) {
610 _objectBuffer = buf;
611 }
612 }
613
614 /**
615 * Method for accessing object useful for building arrays of
616 * primitive types (such as int[]).
617 */
618 public final ArrayBuilders getArrayBuilders()
619 {
620 if (_arrayBuilders == null) {
621 _arrayBuilders = new ArrayBuilders();
622 }
623 return _arrayBuilders;
624 }
625
626 /*
627 /**********************************************************
628 /* Extended API: handler instantiation
629 /**********************************************************
630 */
631
632 public abstract JsonDeserializer<Object> deserializerInstance(Annotated annotated,
633 Object deserDef)
634 throws JsonMappingException;
635
636 public abstract KeyDeserializer keyDeserializerInstance(Annotated annotated,
637 Object deserDef)
638 throws JsonMappingException;
639
640 /*
641 /**********************************************************
642 /* Extended API: resolving contextual deserializers; called
643 /* by structured deserializers for their value/component
644 /* deserializers
645 /**********************************************************
646 */
647
648 /**
649 * Method called for primary property deserializers (ones
650 * directly created to deserialize values of a POJO property),
651 * to handle details of resolving
652 * {@link ContextualDeserializer} with given property context.
653 *
654 * @param prop Property for which the given primary deserializer is used; never null.
655 *
656 * @since 2.5
657 */
658 public JsonDeserializer<?> handlePrimaryContextualization(JsonDeserializer<?> deser,
659 BeanProperty prop, JavaType type)
660 throws JsonMappingException
661 {
662 if (deser instanceof ContextualDeserializer) {
663 _currentType = new LinkedNode<JavaType>(type, _currentType);
664 try {
665 deser = ((ContextualDeserializer) deser).createContextual(this, prop);
666 } finally {
667 _currentType = _currentType.next();
668 }
669 }
670 return deser;
671 }
672
673 /**
674 * Method called for secondary property deserializers (ones
675 * NOT directly created to deal with an annotatable POJO property,
676 * but instead created as a component -- such as value deserializers
677 * for structured types, or deserializers for root values)
678 * to handle details of resolving
679 * {@link ContextualDeserializer} with given property context.
680 * Given that these deserializers are not directly related to given property
681 * (or, in case of root value property, to any property), annotations
682 * accessible may or may not be relevant.
683 *
684 * @param prop Property for which deserializer is used, if any; null
685 * when deserializing root values
686 *
687 * @since 2.5
688 */
689 public JsonDeserializer<?> handleSecondaryContextualization(JsonDeserializer<?> deser,
690 BeanProperty prop, JavaType type)
691 throws JsonMappingException
692 {
693 if (deser instanceof ContextualDeserializer) {
694 _currentType = new LinkedNode<JavaType>(type, _currentType);
695 try {
696 deser = ((ContextualDeserializer) deser).createContextual(this, prop);
697 } finally {
698 _currentType = _currentType.next();
699 }
700 }
701 return deser;
702 }
703
704 /*
705 /**********************************************************
706 /* Parsing methods that may use reusable/-cyclable objects
707 /**********************************************************
708 */
709
710 /**
711 * Convenience method for parsing a Date from given String, using
712 * currently configured date format (accessed using
713 * {@link DeserializationConfig#getDateFormat()}).
714 *<p>
715 * Implementation will handle thread-safety issues related to
716 * date formats such that first time this method is called,
717 * date format is cloned, and cloned instance will be retained
718 * for use during this deserialization round.
719 */
720 public Date parseDate(String dateStr) throws IllegalArgumentException
721 {
722 try {
723 DateFormat df = getDateFormat();
724 return df.parse(dateStr);
725 } catch (ParseException e) {
726 throw new IllegalArgumentException(String.format(
727 "Failed to parse Date value '%s': %s", dateStr,
728 ClassUtil.exceptionMessage(e)));
729 }
730 }
731
732 /**
733 * Convenience method for constructing Calendar instance set
734 * to specified time, to be modified and used by caller.
735 */
736 public Calendar constructCalendar(Date d) {
737 // 08-Jan-2008, tatu: not optimal, but should work for the most part; let's revise as needed.
738 Calendar c = Calendar.getInstance(getTimeZone());
739 c.setTime(d);
740 return c;
741 }
742
743 /*
744 /**********************************************************
745 /* Convenience methods for reading parsed values
746 /**********************************************************
747 */
748
749 /**
750 * Convenience method that may be used by composite or container deserializers,
751 * for reading one-off values contained (for sequences, it is more efficient
752 * to actually fetch deserializer once for the whole collection).
753 *<p>
754 * NOTE: when deserializing values of properties contained in composite types,
755 * rather use {@link #readPropertyValue(JsonParser, BeanProperty, Class)};
756 * this method does not allow use of contextual annotations.
757 *
758 * @since 2.4
759 */
760 public <T> T readValue(JsonParser p, Class<T> type) throws IOException {
761 return readValue(p, getTypeFactory().constructType(type));
762 }
763
764 /**
765 * @since 2.4
766 */
767 @SuppressWarnings("unchecked")
768 public <T> T readValue(JsonParser p, JavaType type) throws IOException {
769 JsonDeserializer<Object> deser = findRootValueDeserializer(type);
770 if (deser == null) {
771 reportBadDefinition(type,
772 "Could not find JsonDeserializer for type "+ClassUtil.getTypeDescription(type));
773 }
774 return (T) deser.deserialize(p, this);
775 }
776
777 /**
778 * Convenience method that may be used by composite or container deserializers,
779 * for reading one-off values for the composite type, taking into account
780 * annotations that the property (passed to this method -- usually property that
781 * has custom serializer that called this method) has.
782 *
783 * @since 2.4
784 */
785 public <T> T readPropertyValue(JsonParser p, BeanProperty prop, Class<T> type) throws IOException {
786 return readPropertyValue(p, prop, getTypeFactory().constructType(type));
787 }
788
789 /**
790 * @since 2.4
791 */
792 @SuppressWarnings("unchecked")
793 public <T> T readPropertyValue(JsonParser p, BeanProperty prop, JavaType type) throws IOException {
794 JsonDeserializer<Object> deser = findContextualValueDeserializer(type, prop);
795 if (deser == null) {
796 return reportBadDefinition(type, String.format(
797 "Could not find JsonDeserializer for type %s (via property %s)",
798 ClassUtil.getTypeDescription(type), ClassUtil.nameOf(prop)));
799 }
800 return (T) deser.deserialize(p, this);
801 }
802
803 /**
804 * @since 2.10
805 */
806 public JsonNode readTree(JsonParser p) throws IOException {
807 JsonToken t = p.currentToken();
808 if (t == null) {
809 t = p.nextToken();
810 if (t == null) {
811 return getNodeFactory().missingNode();
812 }
813 }
814 if (t == JsonToken.VALUE_NULL) {
815 return getNodeFactory().nullNode();
816 }
817 return (JsonNode) findRootValueDeserializer(_config.constructType(JsonNode.class))
818 .deserialize(p, this);
819 }
820
821 /*
822 /**********************************************************
823 /* Methods for problem handling
824 /**********************************************************
825 */
826
827 /**
828 * Method that deserializers should call if they encounter an unrecognized
829 * property (and once that is not explicitly designed as ignorable), to
830 * inform possibly configured {@link DeserializationProblemHandler}s and
831 * let it handle the problem.
832 *
833 * @return True if there was a configured problem handler that was able to handle the
834 * problem
835 */
836 public boolean handleUnknownProperty(JsonParser p, JsonDeserializer<?> deser,
837 Object instanceOrClass, String propName)
838 throws IOException
839 {
840 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
841 while (h != null) {
842 // Can bail out if it's handled
843 if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) {
844 return true;
845 }
846 h = h.next();
847 }
848 // Nope, not handled. Potentially that's a problem...
849 if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
850 p.skipChildren();
851 return true;
852 }
853 // Do we know properties that are expected instead?
854 Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames();
855 throw UnrecognizedPropertyException.from(_parser,
856 instanceOrClass, propName, propIds);
857 }
858
859 /**
860 * Method that deserializers should call if they encounter a String value
861 * that cannot be converted to expected key of a {@link java.util.Map}
862 * valued property.
863 * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue}
864 * on configured handlers, if any, to allow for recovery; if recovery does not
865 * succeed, will throw {@link InvalidFormatException} with given message.
866 *
867 * @param keyClass Expected type for key
868 * @param keyValue String value from which to deserialize key
869 * @param msg Error message template caller wants to use if exception is to be thrown
870 * @param msgArgs Optional arguments to use for message, if any
871 *
872 * @return Key value to use
873 *
874 * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
875 *
876 * @since 2.8
877 */
878 public Object handleWeirdKey(Class<?> keyClass, String keyValue,
879 String msg, Object... msgArgs)
880 throws IOException
881 {
882 // but if not handled, just throw exception
883 msg = _format(msg, msgArgs);
884 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
885 while (h != null) {
886 // Can bail out if it's handled
887 Object key = h.value().handleWeirdKey(this, keyClass, keyValue, msg);
888 if (key != DeserializationProblemHandler.NOT_HANDLED) {
889 // Sanity check for broken handlers, otherwise nasty to debug:
890 if ((key == null) || keyClass.isInstance(key)) {
891 return key;
892 }
893 throw weirdStringException(keyValue, keyClass, String.format(
894 "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
895 ClassUtil.getClassDescription(keyClass),
896 ClassUtil.getClassDescription(key)
897 ));
898 }
899 h = h.next();
900 }
901 throw weirdKeyException(keyClass, keyValue, msg);
902 }
903
904 /**
905 * Method that deserializers should call if they encounter a String value
906 * that cannot be converted to target property type, in cases where some
907 * String values could be acceptable (either with different settings,
908 * or different value).
909 * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdStringValue}
910 * on configured handlers, if any, to allow for recovery; if recovery does not
911 * succeed, will throw {@link InvalidFormatException} with given message.
912 *
913 * @param targetClass Type of property into which incoming number should be converted
914 * @param value String value from which to deserialize property value
915 * @param msg Error message template caller wants to use if exception is to be thrown
916 * @param msgArgs Optional arguments to use for message, if any
917 *
918 * @return Property value to use
919 *
920 * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
921 *
922 * @since 2.8
923 */
924 public Object handleWeirdStringValue(Class<?> targetClass, String value,
925 String msg, Object... msgArgs)
926 throws IOException
927 {
928 // but if not handled, just throw exception
929 msg = _format(msg, msgArgs);
930 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
931 while (h != null) {
932 // Can bail out if it's handled
933 Object instance = h.value().handleWeirdStringValue(this, targetClass, value, msg);
934 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
935 // Sanity check for broken handlers, otherwise nasty to debug:
936 if (_isCompatible(targetClass, instance)) {
937 return instance;
938 }
939 throw weirdStringException(value, targetClass, String.format(
940 "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
941 ClassUtil.getClassDescription(targetClass),
942 ClassUtil.getClassDescription(instance)
943 ));
944 }
945 h = h.next();
946 }
947 throw weirdStringException(value, targetClass, msg);
948 }
949
950 /**
951 * Method that deserializers should call if they encounter a numeric value
952 * that cannot be converted to target property type, in cases where some
953 * numeric values could be acceptable (either with different settings,
954 * or different numeric value).
955 * Default implementation will try to call {@link DeserializationProblemHandler#handleWeirdNumberValue}
956 * on configured handlers, if any, to allow for recovery; if recovery does not
957 * succeed, will throw {@link InvalidFormatException} with given message.
958 *
959 * @param targetClass Type of property into which incoming number should be converted
960 * @param value Number value from which to deserialize property value
961 * @param msg Error message template caller wants to use if exception is to be thrown
962 * @param msgArgs Optional arguments to use for message, if any
963 *
964 * @return Property value to use
965 *
966 * @throws IOException To indicate unrecoverable problem, usually based on <code>msg</code>
967 *
968 * @since 2.8
969 */
970 public Object handleWeirdNumberValue(Class<?> targetClass, Number value,
971 String msg, Object... msgArgs)
972 throws IOException
973 {
974 msg = _format(msg, msgArgs);
975 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
976 while (h != null) {
977 // Can bail out if it's handled
978 Object key = h.value().handleWeirdNumberValue(this, targetClass, value, msg);
979 if (key != DeserializationProblemHandler.NOT_HANDLED) {
980 // Sanity check for broken handlers, otherwise nasty to debug:
981 if (_isCompatible(targetClass, key)) {
982 return key;
983 }
984 throw weirdNumberException(value, targetClass, _format(
985 "DeserializationProblemHandler.handleWeirdNumberValue() for type %s returned value of type %s",
986 ClassUtil.getClassDescription(targetClass),
987 ClassUtil.getClassDescription(key)
988 ));
989 }
990 h = h.next();
991 }
992 throw weirdNumberException(value, targetClass, msg);
993 }
994
995 public Object handleWeirdNativeValue(JavaType targetType, Object badValue,
996 JsonParser p)
997 throws IOException
998 {
999 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1000 final Class<?> raw = targetType.getRawClass();
1001 for (; h != null; h = h.next()) {
1002 // Can bail out if it's handled
1003 Object goodValue = h.value().handleWeirdNativeValue(this, targetType, badValue, p);
1004 if (goodValue != DeserializationProblemHandler.NOT_HANDLED) {
1005 // Sanity check for broken handlers, otherwise nasty to debug:
1006 if ((goodValue == null) || raw.isInstance(goodValue)) {
1007 return goodValue;
1008 }
1009 throw JsonMappingException.from(p, _format(
1010 "DeserializationProblemHandler.handleWeirdNativeValue() for type %s returned value of type %s",
1011 ClassUtil.getClassDescription(targetType),
1012 ClassUtil.getClassDescription(goodValue)
1013 ));
1014 }
1015 }
1016 throw weirdNativeValueException(badValue, raw);
1017 }
1018
1019 /**
1020 * Method that deserializers should call if they fail to instantiate value
1021 * due to lack of viable instantiator (usually creator, that is, constructor
1022 * or static factory method). Method should be called at point where value
1023 * has not been decoded, so that handler has a chance to handle decoding
1024 * using alternate mechanism, and handle underlying content (possibly by
1025 * just skipping it) to keep input state valid
1026 *
1027 * @param instClass Type that was to be instantiated
1028 * @param valueInst (optional) Value instantiator to be used, if any; null if type does not
1029 * use one for instantiation (custom deserialiers don't; standard POJO deserializer does)
1030 * @param p Parser that points to the JSON value to decode
1031 *
1032 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1033 *
1034 * @since 2.9 (2.8 had alternate that did not take <code>ValueInstantiator</code>)
1035 */
1036 @SuppressWarnings("resource")
1037 public Object handleMissingInstantiator(Class<?> instClass, ValueInstantiator valueInst,
1038 JsonParser p, String msg, Object... msgArgs)
1039 throws IOException
1040 {
1041 if (p == null) {
1042 p = getParser();
1043 }
1044 msg = _format(msg, msgArgs);
1045 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1046 while (h != null) {
1047 // Can bail out if it's handled
1048 Object instance = h.value().handleMissingInstantiator(this,
1049 instClass, valueInst, p, msg);
1050 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
1051 // Sanity check for broken handlers, otherwise nasty to debug:
1052 if (_isCompatible(instClass, instance)) {
1053 return instance;
1054 }
1055 reportBadDefinition(constructType(instClass), String.format(
1056 "DeserializationProblemHandler.handleMissingInstantiator() for type %s returned value of type %s",
1057 ClassUtil.getClassDescription(instClass),
1058 ClassUtil.getClassDescription((instance)
1059 )));
1060 }
1061 h = h.next();
1062 }
1063
1064 // 16-Oct-2016, tatu: This is either a definition problem (if no applicable creator
1065 // exists), or input mismatch problem (otherwise) since none of existing creators
1066 // match with token.
1067 // 24-Oct-2019, tatu: Further, as per [databind#2522], passing `null` ValueInstantiator
1068 // should simply trigger definition problem
1069 if (valueInst == null ) {
1070 msg = String.format("Cannot construct instance of %s: %s",
1071 ClassUtil.nameOf(instClass), msg);
1072 return reportBadDefinition(instClass, msg);
1073 }
1074 if (!valueInst.canInstantiate()) {
1075 msg = String.format("Cannot construct instance of %s (no Creators, like default constructor, exist): %s",
1076 ClassUtil.nameOf(instClass), msg);
1077 return reportBadDefinition(instClass, msg);
1078 }
1079 msg = String.format("Cannot construct instance of %s (although at least one Creator exists): %s",
1080 ClassUtil.nameOf(instClass), msg);
1081 return reportInputMismatch(instClass, msg);
1082 }
1083
1084 /**
1085 * Method that deserializers should call if they fail to instantiate value
1086 * due to an exception that was thrown by constructor (or other mechanism used
1087 * to create instances).
1088 * Default implementation will try to call {@link DeserializationProblemHandler#handleInstantiationProblem}
1089 * on configured handlers, if any, to allow for recovery; if recovery does not
1090 * succeed, will throw exception constructed with {@link #instantiationException}.
1091 *
1092 * @param instClass Type that was to be instantiated
1093 * @param argument (optional) Argument that was passed to constructor or equivalent
1094 * instantiator; often a {@link java.lang.String}.
1095 * @param t Exception that caused failure
1096 *
1097 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1098 *
1099 * @since 2.8
1100 */
1101 public Object handleInstantiationProblem(Class<?> instClass, Object argument,
1102 Throwable t)
1103 throws IOException
1104 {
1105 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1106 while (h != null) {
1107 // Can bail out if it's handled
1108 Object instance = h.value().handleInstantiationProblem(this, instClass, argument, t);
1109 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
1110 // Sanity check for broken handlers, otherwise nasty to debug:
1111 if (_isCompatible(instClass, instance)) {
1112 return instance;
1113 }
1114 reportBadDefinition(constructType(instClass), String.format(
1115 "DeserializationProblemHandler.handleInstantiationProblem() for type %s returned value of type %s",
1116 ClassUtil.getClassDescription(instClass),
1117 ClassUtil.classNameOf(instance)
1118 ));
1119 }
1120 h = h.next();
1121 }
1122 // 18-May-2016, tatu: Only wrap if not already a valid type to throw
1123 ClassUtil.throwIfIOE(t);
1124 // [databind#2164]: but see if wrapping is desired
1125 if (!isEnabled(DeserializationFeature.WRAP_EXCEPTIONS)) {
1126 ClassUtil.throwIfRTE(t);
1127 }
1128 throw instantiationException(instClass, t);
1129 }
1130
1131 /**
1132 * Method that deserializers should call if the first token of the value to
1133 * deserialize is of unexpected type (that is, type of token that deserializer
1134 * cannot handle). This could occur, for example, if a Number deserializer
1135 * encounter {@link JsonToken#START_ARRAY} instead of
1136 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1137 *
1138 * @param instClass Type that was to be instantiated
1139 * @param p Parser that points to the JSON value to decode
1140 *
1141 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1142 *
1143 * @since 2.8
1144 */
1145 public Object handleUnexpectedToken(Class<?> instClass, JsonParser p)
1146 throws IOException
1147 {
1148 return handleUnexpectedToken(constructType(instClass), p.getCurrentToken(), p, null);
1149 }
1150
1151 /**
1152 * Method that deserializers should call if the first token of the value to
1153 * deserialize is of unexpected type (that is, type of token that deserializer
1154 * cannot handle). This could occur, for example, if a Number deserializer
1155 * encounter {@link JsonToken#START_ARRAY} instead of
1156 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1157 *
1158 * @param instClass Type that was to be instantiated
1159 * @param t Token encountered that does match expected
1160 * @param p Parser that points to the JSON value to decode
1161 *
1162 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1163 *
1164 * @since 2.8
1165 */
1166 public Object handleUnexpectedToken(Class<?> instClass, JsonToken t,
1167 JsonParser p, String msg, Object... msgArgs)
1168 throws IOException
1169 {
1170 return handleUnexpectedToken(constructType(instClass), t, p, msg, msgArgs);
1171 }
1172
1173 /**
1174 * Method that deserializers should call if the first token of the value to
1175 * deserialize is of unexpected type (that is, type of token that deserializer
1176 * cannot handle). This could occur, for example, if a Number deserializer
1177 * encounter {@link JsonToken#START_ARRAY} instead of
1178 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1179 *
1180 * @param targetType Type that was to be instantiated
1181 * @param p Parser that points to the JSON value to decode
1182 *
1183 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1184 *
1185 * @since 2.10
1186 */
1187 public Object handleUnexpectedToken(JavaType targetType, JsonParser p)
1188 throws IOException
1189 {
1190 return handleUnexpectedToken(targetType, p.getCurrentToken(), p, null);
1191 }
1192
1193 /**
1194 * Method that deserializers should call if the first token of the value to
1195 * deserialize is of unexpected type (that is, type of token that deserializer
1196 * cannot handle). This could occur, for example, if a Number deserializer
1197 * encounter {@link JsonToken#START_ARRAY} instead of
1198 * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
1199 *
1200 * @param targetType Type that was to be instantiated
1201 * @param t Token encountered that does not match expected
1202 * @param p Parser that points to the JSON value to decode
1203 *
1204 * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
1205 *
1206 * @since 2.10
1207 */
1208 public Object handleUnexpectedToken(JavaType targetType, JsonToken t,
1209 JsonParser p, String msg, Object... msgArgs)
1210 throws IOException
1211 {
1212 msg = _format(msg, msgArgs);
1213 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1214 while (h != null) {
1215 Object instance = h.value().handleUnexpectedToken(this,
1216 targetType, t, p, msg);
1217 if (instance != DeserializationProblemHandler.NOT_HANDLED) {
1218 if (_isCompatible(targetType.getRawClass(), instance)) {
1219 return instance;
1220 }
1221 reportBadDefinition(targetType, String.format(
1222 "DeserializationProblemHandler.handleUnexpectedToken() for type %s returned value of type %s",
1223 ClassUtil.getClassDescription(targetType),
1224 ClassUtil.classNameOf(instance)
1225 ));
1226 }
1227 h = h.next();
1228 }
1229 if (msg == null) {
1230 if (t == null) {
1231 msg = String.format("Unexpected end-of-input when binding data into %s",
1232 ClassUtil.getTypeDescription(targetType));
1233 } else {
1234 msg = String.format("Cannot deserialize instance of %s out of %s token",
1235 ClassUtil.getTypeDescription(targetType), t);
1236 }
1237 }
1238 // 18-Jun-2020, tatu: to resolve [databind#2770], force access to `getText()` for scalars
1239 if ((t != null) && t.isScalarValue()) {
1240 p.getText();
1241 }
1242 reportInputMismatch(targetType, msg);
1243 return null; // never gets here
1244 }
1245
1246 /**
1247 * Method that deserializers should call if they encounter a type id
1248 * (for polymorphic deserialization) that cannot be resolved to an
1249 * actual type; usually since there is no mapping defined.
1250 * Default implementation will try to call {@link DeserializationProblemHandler#handleUnknownTypeId}
1251 * on configured handlers, if any, to allow for recovery; if recovery does not
1252 * succeed, will throw exception constructed with {@link #invalidTypeIdException}.
1253 *
1254 * @param baseType Base type from which resolution starts
1255 * @param id Type id that could not be converted
1256 * @param extraDesc Additional problem description to add to default exception message,
1257 * if resolution fails.
1258 *
1259 * @return {@link JavaType} that id resolves to
1260 *
1261 * @throws IOException To indicate unrecoverable problem, if resolution cannot
1262 * be made to work
1263 *
1264 * @since 2.8
1265 */
1266 public JavaType handleUnknownTypeId(JavaType baseType, String id,
1267 TypeIdResolver idResolver, String extraDesc) throws IOException
1268 {
1269 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1270 while (h != null) {
1271 // Can bail out if it's handled
1272 JavaType type = h.value().handleUnknownTypeId(this, baseType, id, idResolver, extraDesc);
1273 if (type != null) {
1274 if (type.hasRawClass(Void.class)) {
1275 return null;
1276 }
1277 // But ensure there's type compatibility
1278 if (type.isTypeOrSubTypeOf(baseType.getRawClass())) {
1279 return type;
1280 }
1281 throw invalidTypeIdException(baseType, id,
1282 "problem handler tried to resolve into non-subtype: "+
1283 ClassUtil.getTypeDescription(type));
1284 }
1285 h = h.next();
1286 }
1287 // 24-May-2016, tatu: Actually we may still not want to fail quite yet
1288 if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
1289 return null;
1290 }
1291 throw invalidTypeIdException(baseType, id, extraDesc);
1292 }
1293
1294 /**
1295 * @since 2.9
1296 */
1297 public JavaType handleMissingTypeId(JavaType baseType,
1298 TypeIdResolver idResolver, String extraDesc) throws IOException
1299 {
1300 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
1301 while (h != null) {
1302 // Can bail out if it's handled
1303 JavaType type = h.value().handleMissingTypeId(this, baseType, idResolver, extraDesc);
1304 if (type != null) {
1305 if (type.hasRawClass(Void.class)) {
1306 return null;
1307 }
1308 // But ensure there's type compatibility
1309 if (type.isTypeOrSubTypeOf(baseType.getRawClass())) {
1310 return type;
1311 }
1312 throw invalidTypeIdException(baseType, null,
1313 "problem handler tried to resolve into non-subtype: "+
1314 ClassUtil.getTypeDescription(type));
1315 }
1316 h = h.next();
1317 }
1318 // 09-Mar-2017, tatu: We may want to consider yet another feature at some
1319 // point to allow returning `null`... but that seems bit risky for now
1320 // if (!isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
1321 // return null;
1322 // }
1323 throw missingTypeIdException(baseType, extraDesc);
1324 }
1325
1326 /**
1327 * Method that deserializer may call if it is called to do an update ("merge")
1328 * but deserializer operates on a non-mergeable type. Although this should
1329 * usually be caught earlier, sometimes it may only be caught during operation
1330 * and if so this is the method to call.
1331 * Note that if {@link MapperFeature#IGNORE_MERGE_FOR_UNMERGEABLE} is enabled,
1332 * this method will simply return null; otherwise {@link InvalidDefinitionException}
1333 * will be thrown.
1334 *
1335 * @since 2.10
1336 */
1337 public void handleBadMerge(JsonDeserializer<?> deser) throws JsonMappingException
1338 {
1339 if (!isEnabled(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)) {
1340 JavaType type = constructType(deser.handledType());
1341 String msg = String.format("Invalid configuration: values of type %s cannot be merged",
1342 ClassUtil.getTypeDescription(type));
1343 throw InvalidDefinitionException.from(getParser(), msg, type);
1344 }
1345 }
1346
1347 /**
1348 * @since 2.9.2
1349 */
1350 protected boolean _isCompatible(Class<?> target, Object value)
1351 {
1352 if ((value == null) || target.isInstance(value)) {
1353 return true;
1354 }
1355 // [databind#1767]: Make sure to allow wrappers for primitive fields
1356 return target.isPrimitive()
1357 && ClassUtil.wrapperType(target).isInstance(value);
1358 }
1359
1360 /*
1361 /**********************************************************
1362 /* Methods for problem reporting, in cases where recovery
1363 /* is not considered possible: input problem
1364 /**********************************************************
1365 */
1366
1367 /**
1368 * Method for deserializers to call
1369 * when the token encountered was of type different than what <b>should</b>
1370 * be seen at that position, usually within a sequence of expected tokens.
1371 * Note that this method will throw a {@link JsonMappingException} and no
1372 * recovery is attempted (via {@link DeserializationProblemHandler}, as
1373 * problem is considered to be difficult to recover from, in general.
1374 *
1375 * @since 2.9
1376 */
1377 public void reportWrongTokenException(JsonDeserializer<?> deser,
1378 JsonToken expToken, String msg, Object... msgArgs)
1379 throws JsonMappingException
1380 {
1381 msg = _format(msg, msgArgs);
1382 throw wrongTokenException(getParser(), deser.handledType(), expToken, msg);
1383 }
1384
1385 /**
1386 * Method for deserializers to call
1387 * when the token encountered was of type different than what <b>should</b>
1388 * be seen at that position, usually within a sequence of expected tokens.
1389 * Note that this method will throw a {@link JsonMappingException} and no
1390 * recovery is attempted (via {@link DeserializationProblemHandler}, as
1391 * problem is considered to be difficult to recover from, in general.
1392 *
1393 * @since 2.9
1394 */
1395 public void reportWrongTokenException(JavaType targetType,
1396 JsonToken expToken, String msg, Object... msgArgs)
1397 throws JsonMappingException
1398 {
1399 msg = _format(msg, msgArgs);
1400 throw wrongTokenException(getParser(), targetType, expToken, msg);
1401 }
1402
1403 /**
1404 * Method for deserializers to call
1405 * when the token encountered was of type different than what <b>should</b>
1406 * be seen at that position, usually within a sequence of expected tokens.
1407 * Note that this method will throw a {@link JsonMappingException} and no
1408 * recovery is attempted (via {@link DeserializationProblemHandler}, as
1409 * problem is considered to be difficult to recover from, in general.
1410 *
1411 * @since 2.9
1412 */
1413 public void reportWrongTokenException(Class<?> targetType,
1414 JsonToken expToken, String msg, Object... msgArgs)
1415 throws JsonMappingException
1416 {
1417 msg = _format(msg, msgArgs);
1418 throw wrongTokenException(getParser(), targetType, expToken, msg);
1419 }
1420
1421 /**
1422 * @since 2.8
1423 */
1424 public <T> T reportUnresolvedObjectId(ObjectIdReader oidReader, Object bean)
1425 throws JsonMappingException
1426 {
1427 String msg = String.format("No Object Id found for an instance of %s, to assign to property '%s'",
1428 ClassUtil.classNameOf(bean), oidReader.propertyName);
1429 return reportInputMismatch(oidReader.idProperty, msg);
1430 }
1431
1432 /**
1433 * Helper method used to indicate a problem with input in cases where more
1434 * specific <code>reportXxx()</code> method was not available.
1435 *
1436 * @since 2.9
1437 */
1438 public <T> T reportInputMismatch(JsonDeserializer<?> src,
1439 String msg, Object... msgArgs) throws JsonMappingException
1440 {
1441 msg = _format(msg, msgArgs);
1442 throw MismatchedInputException.from(getParser(), src.handledType(), msg);
1443 }
1444
1445 /**
1446 * Helper method used to indicate a problem with input in cases where more
1447 * specific <code>reportXxx()</code> method was not available.
1448 *
1449 * @since 2.9
1450 */
1451 public <T> T reportInputMismatch(Class<?> targetType,
1452 String msg, Object... msgArgs) throws JsonMappingException
1453 {
1454 msg = _format(msg, msgArgs);
1455 throw MismatchedInputException.from(getParser(), targetType, msg);
1456 }
1457
1458 /**
1459 * Helper method used to indicate a problem with input in cases where more
1460 * specific <code>reportXxx()</code> method was not available.
1461 *
1462 * @since 2.9
1463 */
1464 public <T> T reportInputMismatch(JavaType targetType,
1465 String msg, Object... msgArgs) throws JsonMappingException
1466 {
1467 msg = _format(msg, msgArgs);
1468 throw MismatchedInputException.from(getParser(), targetType, msg);
1469 }
1470
1471 /**
1472 * Helper method used to indicate a problem with input in cases where more
1473 * specific <code>reportXxx()</code> method was not available.
1474 *
1475 * @since 2.9
1476 */
1477 public <T> T reportInputMismatch(BeanProperty prop,
1478 String msg, Object... msgArgs) throws JsonMappingException
1479 {
1480 msg = _format(msg, msgArgs);
1481 JavaType type = (prop == null) ? null : prop.getType();
1482 final MismatchedInputException e = MismatchedInputException.from(getParser(), type, msg);
1483 // [databind#2357]: Include property name, if we have it
1484 if (prop != null) {
1485 AnnotatedMember member = prop.getMember();
1486 if (member != null) {
1487 e.prependPath(member.getDeclaringClass(), prop.getName());
1488 }
1489 }
1490 throw e;
1491 }
1492
1493 /**
1494 * Helper method used to indicate a problem with input in cases where more
1495 * specific <code>reportXxx()</code> method was not available.
1496 *
1497 * @since 2.10
1498 */
1499 public <T> T reportPropertyInputMismatch(Class<?> targetType, String propertyName,
1500 String msg, Object... msgArgs) throws JsonMappingException
1501 {
1502 msg = _format(msg, msgArgs);
1503 MismatchedInputException e = MismatchedInputException.from(getParser(), targetType, msg);
1504 if (propertyName != null) {
1505 e.prependPath(targetType, propertyName);
1506 }
1507 throw e;
1508 }
1509
1510 /**
1511 * Helper method used to indicate a problem with input in cases where more
1512 * specific <code>reportXxx()</code> method was not available.
1513 *
1514 * @since 2.10
1515 */
1516 public <T> T reportPropertyInputMismatch(JavaType targetType, String propertyName,
1517 String msg, Object... msgArgs) throws JsonMappingException
1518 {
1519 return reportPropertyInputMismatch(targetType.getRawClass(), propertyName, msg, msgArgs);
1520 }
1521
1522 public <T> T reportTrailingTokens(Class<?> targetType,
1523 JsonParser p, JsonToken trailingToken) throws JsonMappingException
1524 {
1525 throw MismatchedInputException.from(p, targetType, String.format(
1526 "Trailing token (of type %s) found after value (bound as %s): not allowed as per `DeserializationFeature.FAIL_ON_TRAILING_TOKENS`",
1527 trailingToken, ClassUtil.nameOf(targetType)
1528 ));
1529 }
1530
1531 @Deprecated // since 2.9
1532 public void reportWrongTokenException(JsonParser p,
1533 JsonToken expToken, String msg, Object... msgArgs)
1534 throws JsonMappingException
1535 {
1536 msg = _format(msg, msgArgs);
1537 throw wrongTokenException(p, expToken, msg);
1538 }
1539
1540 /**
1541 * Helper method for reporting a problem with unhandled unknown property.
1542 *
1543 * @param instanceOrClass Either value being populated (if one has been
1544 * instantiated), or Class that indicates type that would be (or
1545 * have been) instantiated
1546 * @param deser Deserializer that had the problem, if called by deserializer
1547 * (or on behalf of one)
1548 *
1549 * @deprecated Since 2.8 call {@link #handleUnknownProperty} instead
1550 */
1551 @Deprecated
1552 public void reportUnknownProperty(Object instanceOrClass, String fieldName,
1553 JsonDeserializer<?> deser)
1554 throws JsonMappingException
1555 {
1556 if (isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
1557 // Do we know properties that are expected instead?
1558 Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames();
1559 throw UnrecognizedPropertyException.from(_parser,
1560 instanceOrClass, fieldName, propIds);
1561 }
1562 }
1563
1564 /**
1565 * @since 2.8
1566 *
1567 * @deprecated Since 2.9: not clear this ever occurs
1568 */
1569 @Deprecated // since 2.9
1570 public void reportMissingContent(String msg, Object... msgArgs) throws JsonMappingException {
1571 throw MismatchedInputException.from(getParser(), (JavaType) null, "No content to map due to end-of-input");
1572 }
1573
1574 /*
1575 /**********************************************************
1576 /* Methods for problem reporting, in cases where recovery
1577 /* is not considered possible: POJO definition problems
1578 /**********************************************************
1579 */
1580
1581 /**
1582 * Helper method called to indicate problem in POJO (serialization) definitions or settings
1583 * regarding specific Java type, unrelated to actual JSON content to map.
1584 * Default behavior is to construct and throw a {@link JsonMappingException}.
1585 *
1586 * @since 2.9
1587 */
1588 public <T> T reportBadTypeDefinition(BeanDescription bean,
1589 String msg, Object... msgArgs) throws JsonMappingException {
1590 msg = _format(msg, msgArgs);
1591 String beanDesc = ClassUtil.nameOf(bean.getBeanClass());
1592 msg = String.format("Invalid type definition for type %s: %s", beanDesc, msg);
1593 throw InvalidDefinitionException.from(_parser, msg, bean, null);
1594 }
1595
1596 /**
1597 * Helper method called to indicate problem in POJO (serialization) definitions or settings
1598 * regarding specific property (of a type), unrelated to actual JSON content to map.
1599 * Default behavior is to construct and throw a {@link JsonMappingException}.
1600 *
1601 * @since 2.9
1602 */
1603 public <T> T reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop,
1604 String msg, Object... msgArgs) throws JsonMappingException {
1605 msg = _format(msg, msgArgs);
1606 String propName = ClassUtil.nameOf(prop);
1607 String beanDesc = ClassUtil.nameOf(bean.getBeanClass());
1608 msg = String.format("Invalid definition for property %s (of type %s): %s",
1609 propName, beanDesc, msg);
1610 throw InvalidDefinitionException.from(_parser, msg, bean, prop);
1611 }
1612
1613 @Override
1614 public <T> T reportBadDefinition(JavaType type, String msg) throws JsonMappingException {
1615 throw InvalidDefinitionException.from(_parser, msg, type);
1616 }
1617
1618 /**
1619 * @deprecated Since 2.10 use {@link #handleBadMerge} instead
1620 */
1621 @Deprecated // since 2.10
1622 public <T> T reportBadMerge(JsonDeserializer<?> deser) throws JsonMappingException {
1623 handleBadMerge(deser);
1624 return null;
1625 }
1626
1627 /*
1628 /**********************************************************
1629 /* Methods for constructing semantic exceptions; usually not
1630 /* to be called directly, call `handleXxx()` instead
1631 /**********************************************************
1632 */
1633
1634 /**
1635 * Helper method for constructing {@link JsonMappingException} to indicate
1636 * that the token encountered was of type different than what <b>should</b>
1637 * be seen at that position, usually within a sequence of expected tokens.
1638 * Note that most of the time this method should NOT be directly called;
1639 * instead, {@link #reportWrongTokenException} should be called and will
1640 * call this method as necessary.
1641 *
1642 * @since 2.9
1643 */
1644 public JsonMappingException wrongTokenException(JsonParser p, JavaType targetType,
1645 JsonToken expToken, String extra)
1646 {
1647 String msg = String.format("Unexpected token (%s), expected %s",
1648 p.getCurrentToken(), expToken);
1649 msg = _colonConcat(msg, extra);
1650 return MismatchedInputException.from(p, targetType, msg);
1651 }
1652
1653 public JsonMappingException wrongTokenException(JsonParser p, Class<?> targetType,
1654 JsonToken expToken, String extra)
1655 {
1656 String msg = String.format("Unexpected token (%s), expected %s",
1657 p.getCurrentToken(), expToken);
1658 msg = _colonConcat(msg, extra);
1659 return MismatchedInputException.from(p, targetType, msg);
1660 }
1661
1662 @Deprecated // since 2.9
1663 public JsonMappingException wrongTokenException(JsonParser p, JsonToken expToken,
1664 String msg)
1665 {
1666 return wrongTokenException(p, (JavaType) null, expToken, msg);
1667 }
1668
1669 /**
1670 * Helper method for constructing exception to indicate that given JSON
1671 * Object field name was not in format to be able to deserialize specified
1672 * key type.
1673 * Note that most of the time this method should NOT be called; instead,
1674 * {@link #handleWeirdKey} should be called which will call this method
1675 * if necessary.
1676 */
1677 public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue,
1678 String msg) {
1679 return InvalidFormatException.from(_parser,
1680 String.format("Cannot deserialize Map key of type %s from String %s: %s",
1681 ClassUtil.nameOf(keyClass), _quotedString(keyValue), msg),
1682 keyValue, keyClass);
1683 }
1684
1685 /**
1686 * Helper method for constructing exception to indicate that input JSON
1687 * String was not suitable for deserializing into given target type.
1688 * Note that most of the time this method should NOT be called; instead,
1689 * {@link #handleWeirdStringValue} should be called which will call this method
1690 * if necessary.
1691 *
1692 * @param value String value from input being deserialized
1693 * @param instClass Type that String should be deserialized into
1694 * @param msgBase Message that describes specific problem
1695 *
1696 * @since 2.1
1697 */
1698 public JsonMappingException weirdStringException(String value, Class<?> instClass,
1699 String msgBase) {
1700 final String msg = String.format("Cannot deserialize value of type %s from String %s: %s",
1701 ClassUtil.nameOf(instClass), _quotedString(value), msgBase);
1702 return InvalidFormatException.from(_parser, msg, value, instClass);
1703 }
1704
1705 /**
1706 * Helper method for constructing exception to indicate that input JSON
1707 * Number was not suitable for deserializing into given target type.
1708 * Note that most of the time this method should NOT be called; instead,
1709 * {@link #handleWeirdNumberValue} should be called which will call this method
1710 * if necessary.
1711 */
1712 public JsonMappingException weirdNumberException(Number value, Class<?> instClass,
1713 String msg) {
1714 return InvalidFormatException.from(_parser,
1715 String.format("Cannot deserialize value of type %s from number %s: %s",
1716 ClassUtil.nameOf(instClass), String.valueOf(value), msg),
1717 value, instClass);
1718 }
1719
1720 /**
1721 * Helper method for constructing exception to indicate that input JSON
1722 * token of type "native value" (see {@link JsonToken#VALUE_EMBEDDED_OBJECT})
1723 * is of incompatible type (and there is no delegating creator or such to use)
1724 * and can not be used to construct value of specified type (usually POJO).
1725 * Note that most of the time this method should NOT be called; instead,
1726 * {@link #handleWeirdNativeValue} should be called which will call this method
1727 *
1728 * @since 2.9
1729 */
1730 public JsonMappingException weirdNativeValueException(Object value, Class<?> instClass)
1731 {
1732 return InvalidFormatException.from(_parser, String.format(
1733 "Cannot deserialize value of type %s from native value (`JsonToken.VALUE_EMBEDDED_OBJECT`) of type %s: incompatible types",
1734 ClassUtil.nameOf(instClass), ClassUtil.classNameOf(value)),
1735 value, instClass);
1736 }
1737
1738 /**
1739 * Helper method for constructing instantiation exception for specified type,
1740 * to indicate problem with physically constructing instance of
1741 * specified class (missing constructor, exception from constructor)
1742 *<p>
1743 * Note that most of the time this method should NOT be called directly; instead,
1744 * {@link #handleInstantiationProblem} should be called which will call this method
1745 * if necessary.
1746 */
1747 public JsonMappingException instantiationException(Class<?> instClass, Throwable cause) {
1748 String excMsg;
1749 if (cause == null) {
1750 excMsg = "N/A";
1751 } else if ((excMsg = ClassUtil.exceptionMessage(cause)) == null) {
1752 excMsg = ClassUtil.nameOf(cause.getClass());
1753 }
1754 String msg = String.format("Cannot construct instance of %s, problem: %s",
1755 ClassUtil.nameOf(instClass), excMsg);
1756 // [databind#2162]: use specific exception type as we don't know if it's
1757 // due to type definition, input, or neither
1758 return ValueInstantiationException.from(_parser, msg, constructType(instClass), cause);
1759 }
1760
1761 /**
1762 * Helper method for constructing instantiation exception for specified type,
1763 * to indicate that instantiation failed due to missing instantiator
1764 * (creator; constructor or factory method).
1765 *<p>
1766 * Note that most of the time this method should NOT be called; instead,
1767 * {@link #handleMissingInstantiator} should be called which will call this method
1768 * if necessary.
1769 */
1770 public JsonMappingException instantiationException(Class<?> instClass, String msg0) {
1771 // [databind#2162]: use specific exception type as we don't know if it's
1772 // due to type definition, input, or neither
1773 return ValueInstantiationException.from(_parser,
1774 String.format("Cannot construct instance of %s: %s",
1775 ClassUtil.nameOf(instClass), msg0),
1776 constructType(instClass));
1777 }
1778
1779 @Override
1780 public JsonMappingException invalidTypeIdException(JavaType baseType, String typeId,
1781 String extraDesc) {
1782 String msg = String.format("Could not resolve type id '%s' as a subtype of %s",
1783 typeId, ClassUtil.getTypeDescription(baseType));
1784 return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, typeId);
1785 }
1786
1787 /**
1788 * @since 2.9
1789 */
1790 public JsonMappingException missingTypeIdException(JavaType baseType,
1791 String extraDesc) {
1792 String msg = String.format("Missing type id when trying to resolve subtype of %s",
1793 baseType);
1794 return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, null);
1795 }
1796
1797 /*
1798 /**********************************************************
1799 /* Deprecated exception factory methods
1800 /**********************************************************
1801 */
1802
1803 /**
1804 * @since 2.5
1805 *
1806 * @deprecated Since 2.8 use {@link #handleUnknownTypeId} instead
1807 */
1808 @Deprecated
1809 public JsonMappingException unknownTypeException(JavaType type, String id,
1810 String extraDesc)
1811 {
1812 String msg = String.format("Could not resolve type id '%s' into a subtype of %s",
1813 id, ClassUtil.getTypeDescription(type));
1814 msg = _colonConcat(msg, extraDesc);
1815 return MismatchedInputException.from(_parser, type, msg);
1816 }
1817
1818 /**
1819 * Helper method for constructing exception to indicate that end-of-input was
1820 * reached while still expecting more tokens to deserialize value of specified type.
1821 *
1822 * @deprecated Since 2.8; currently no way to catch EOF at databind level
1823 */
1824 @Deprecated
1825 public JsonMappingException endOfInputException(Class<?> instClass) {
1826 return MismatchedInputException.from(_parser, instClass,
1827 "Unexpected end-of-input when trying to deserialize a "+instClass.getName());
1828 }
1829
1830 /*
1831 /**********************************************************
1832 /* Deprecated methods for constructing, throwing non-specific
1833 /* JsonMappingExceptions: as of 2.9, should use more specific
1834 /* ones.
1835 /**********************************************************
1836 */
1837
1838 /**
1839 * Fallback method that may be called if no other <code>reportXxx</code>
1840 * is applicable -- but only in that case.
1841 *
1842 * @since 2.8
1843 *
1844 * @deprecated Since 2.9: use a more specific method, or {@link #reportBadDefinition(JavaType, String)},
1845 * or {@link #reportInputMismatch} instead
1846 */
1847 @Deprecated // since 2.9
1848 public void reportMappingException(String msg, Object... msgArgs)
1849 throws JsonMappingException
1850 {
1851 throw JsonMappingException.from(getParser(), _format(msg, msgArgs));
1852 }
1853
1854 /**
1855 * Helper method for constructing generic mapping exception with specified
1856 * message and current location information.
1857 * Note that application code should almost always call
1858 * one of <code>handleXxx</code> methods, or {@link #reportMappingException(String, Object...)}
1859 * instead.
1860 *
1861 * @since 2.6
1862 *
1863 * @deprecated Since 2.9 use more specific error reporting methods instead
1864 */
1865 @Deprecated
1866 public JsonMappingException mappingException(String message) {
1867 return JsonMappingException.from(getParser(), message);
1868 }
1869
1870 /**
1871 * Helper method for constructing generic mapping exception with specified
1872 * message and current location information
1873 * Note that application code should almost always call
1874 * one of <code>handleXxx</code> methods, or {@link #reportMappingException(String, Object...)}
1875 * instead.
1876 *
1877 * @since 2.6
1878 *
1879 * @deprecated Since 2.9 use more specific error reporting methods instead
1880 */
1881 @Deprecated
1882 public JsonMappingException mappingException(String msg, Object... msgArgs) {
1883 return JsonMappingException.from(getParser(), _format(msg, msgArgs));
1884 }
1885
1886 /**
1887 * Helper method for constructing generic mapping exception for specified type
1888 *
1889 * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
1890 */
1891 @Deprecated
1892 public JsonMappingException mappingException(Class<?> targetClass) {
1893 return mappingException(targetClass, _parser.getCurrentToken());
1894 }
1895
1896 /**
1897 * @deprecated Since 2.8 use {@link #handleUnexpectedToken(Class, JsonParser)} instead
1898 */
1899 @Deprecated
1900 public JsonMappingException mappingException(Class<?> targetClass, JsonToken token) {
1901 return JsonMappingException.from(_parser,
1902 String.format("Cannot deserialize instance of %s out of %s token",
1903 ClassUtil.nameOf(targetClass), token));
1904 }
1905
1906 /*
1907 /**********************************************************
1908 /* Other internal methods
1909 /**********************************************************
1910 */
1911
1912 protected DateFormat getDateFormat()
1913 {
1914 if (_dateFormat != null) {
1915 return _dateFormat;
1916 }
1917 /* 24-Feb-2012, tatu: At this point, all timezone configuration
1918 * should have occurred, with respect to default dateformat
1919 * and timezone configuration. But we still better clone
1920 * an instance as formatters may be stateful.
1921 */
1922 DateFormat df = _config.getDateFormat();
1923 _dateFormat = df = (DateFormat) df.clone();
1924 return df;
1925 }
1926 }
1927