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