blob: 77aca58d6125b1b47acfac344750221555488fa8 [file] [log] [blame]
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001package com.fasterxml.jackson.databind;
2
3import java.io.IOException;
Tatu Saloranta06c20b12012-01-29 21:36:52 -08004import java.text.DateFormat;
5import java.text.ParseException;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08006import java.util.*;
Tatu Salorantaaf263c32013-10-24 16:18:50 -07007import java.util.concurrent.atomic.AtomicReference;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08008
Tatu Salorantad71dffa2012-02-07 21:05:21 -08009import com.fasterxml.jackson.annotation.ObjectIdGenerator;
Pascal GĂ©linas184cae32014-02-05 17:35:56 -050010import com.fasterxml.jackson.annotation.ObjectIdResolver;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080011import com.fasterxml.jackson.core.*;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -070012import com.fasterxml.jackson.databind.cfg.ContextAttributes;
Tatu Saloranta06c20b12012-01-29 21:36:52 -080013import com.fasterxml.jackson.databind.deser.*;
Tatu Saloranta34a8adf2012-02-08 22:07:36 -080014import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
Tatuc3a73d02012-01-31 12:45:49 -080015import com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer;
Tatu Salorantadd348562012-07-18 17:25:02 -070016import com.fasterxml.jackson.databind.exc.InvalidFormatException;
Tatu Saloranta06c20b12012-01-29 21:36:52 -080017import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
Tatub37ff332012-01-24 16:19:36 -080018import com.fasterxml.jackson.databind.introspect.Annotated;
Tatuc3a73d02012-01-31 12:45:49 -080019import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
Tatu Saloranta2f823442011-12-23 20:25:27 -080020import com.fasterxml.jackson.databind.node.JsonNodeFactory;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080021import com.fasterxml.jackson.databind.type.TypeFactory;
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -080022import com.fasterxml.jackson.databind.util.*;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080023
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080024/**
Tatu Saloranta97f84822012-01-29 21:38:40 -080025 * Context for the process of deserialization a single root-level value.
26 * Used to allow passing in configuration settings and reusable temporary
27 * objects (scrap arrays, containers).
Tatu Saloranta060ce112012-02-01 22:18:09 -080028 *<p>
29 * Instance life-cycle is such that an partially configured "blueprint" object
30 * is registered with {@link ObjectMapper} (and {@link ObjectReader},
31 * and when an actual instance is needed for deserialization,
32 * a fully configured instance will
Tatu Saloranta71e876b2012-02-05 19:15:48 -080033 * be created using a method in excented API of sub-class
34 * ({@link com.fasterxml.jackson.databind.deser.DefaultDeserializationContext#createInstance}).
Tatu Saloranta060ce112012-02-01 22:18:09 -080035 * Each instance is guaranteed to only be used from single-threaded context;
36 * instances may be reused iff no configuration has changed.
37 *<p>
38 * Defined as abstract class so that implementations must define methods
39 * for reconfiguring blueprints and creating instances.
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080040 */
Tatu Saloranta060ce112012-02-01 22:18:09 -080041public abstract class DeserializationContext
Tatu Saloranta9439a312013-03-02 13:13:09 -080042 extends DatabindContext
Tatu Saloranta0e114112012-10-06 10:45:41 -070043 implements java.io.Serializable
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080044{
Cowtowncoder7fee92e2015-02-11 16:15:08 -080045 private static final long serialVersionUID = 1L; // 2.6
Tatu Saloranta0e114112012-10-06 10:45:41 -070046
Tatu Saloranta06c20b12012-01-29 21:36:52 -080047 /**
48 * Let's limit length of error messages, for cases where underlying data
49 * may be very large -- no point in spamming logs with megs of meaningless
50 * data.
51 */
Tatu Saloranta060ce112012-02-01 22:18:09 -080052 private final static int MAX_ERROR_STR_LEN = 500;
Tatu Saloranta06c20b12012-01-29 21:36:52 -080053
Tatu Saloranta060ce112012-02-01 22:18:09 -080054 /*
55 /**********************************************************
56 /* Configuration, immutable
57 /**********************************************************
58 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -080059
Tatu Saloranta71e876b2012-02-05 19:15:48 -080060 /**
61 * Object that handle details of {@link JsonDeserializer} caching.
62 */
Tatu Saloranta060ce112012-02-01 22:18:09 -080063 protected final DeserializerCache _cache;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080064
Tatu Saloranta060ce112012-02-01 22:18:09 -080065 /*
66 /**********************************************************
67 /* Configuration, changeable via fluent factories
68 /**********************************************************
69 */
70
71 /**
72 * Read-only factory instance; exposed to let
73 * owners (<code>ObjectMapper</code>, <code>ObjectReader</code>)
74 * access it.
75 */
Tatu Salorantaaa512742012-02-22 22:51:33 -080076 protected final DeserializerFactory _factory;
77
78 /*
79 /**********************************************************
Tatu Saloranta060ce112012-02-01 22:18:09 -080080 /* Configuration that gets set for instances (not blueprints)
Tatu Saloranta71e876b2012-02-05 19:15:48 -080081 /* (partly denormalized for performance)
Tatu Saloranta060ce112012-02-01 22:18:09 -080082 /**********************************************************
83 */
84
Tatu Saloranta71e876b2012-02-05 19:15:48 -080085 /**
86 * Generic deserialization processing configuration
87 */
Tatu Saloranta060ce112012-02-01 22:18:09 -080088 protected final DeserializationConfig _config;
Tatu Saloranta71e876b2012-02-05 19:15:48 -080089
90 /**
91 * Bitmap of {@link DeserializationFeature}s that are enabled
92 */
Tatu Salorantae4f23bb2011-12-23 00:31:35 -080093 protected final int _featureFlags;
Tatu Salorantab2d3c7d2012-01-27 21:41:48 -080094
Tatu Saloranta71e876b2012-02-05 19:15:48 -080095 /**
96 * Currently active view, if any.
97 */
Tatu Salorantab2d3c7d2012-01-27 21:41:48 -080098 protected final Class<?> _view;
Tatu Saloranta06c20b12012-01-29 21:36:52 -080099
100 /**
101 * Currently active parser used for deserialization.
102 * May be different from the outermost parser
103 * when content is buffered.
104 */
Tatu Salorantaf5211582012-10-05 17:09:47 -0700105 protected transient JsonParser _parser;
Tatuc3a73d02012-01-31 12:45:49 -0800106
Tatu Saloranta71e876b2012-02-05 19:15:48 -0800107 /**
108 * Object used for resolving references to injectable
109 * values.
110 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800111 protected final InjectableValues _injectableValues;
112
Tatu Saloranta060ce112012-02-01 22:18:09 -0800113 /*
114 /**********************************************************
115 /* Per-operation reusable helper objects (not for blueprints)
116 /**********************************************************
117 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800118
Tatu Salorantaf5211582012-10-05 17:09:47 -0700119 protected transient ArrayBuilders _arrayBuilders;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800120
Tatu Salorantaf5211582012-10-05 17:09:47 -0700121 protected transient ObjectBuffer _objectBuffer;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800122
Tatu Salorantaf5211582012-10-05 17:09:47 -0700123 protected transient DateFormat _dateFormat;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700124
125 /**
126 * Lazily-constructed holder for per-call attributes.
127 *
128 * @since 2.3
129 */
130 protected transient ContextAttributes _attributes;
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800131
132 /**
133 * Type of {@link JsonDeserializer} (or, more specifically,
134 * {@link ContextualizableDeserializer}) that is being
135 * contextualized currently.
136 *
137 * @since 2.5
138 */
139 protected LinkedNode<JavaType> _currentType;
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800140
141 /*
142 /**********************************************************
143 /* Life-cycle
144 /**********************************************************
145 */
Tatu Saloranta060ce112012-02-01 22:18:09 -0800146
147 protected DeserializationContext(DeserializerFactory df) {
148 this(df, null);
149 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800150
Tatu Saloranta060ce112012-02-01 22:18:09 -0800151 protected DeserializationContext(DeserializerFactory df,
152 DeserializerCache cache)
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800153 {
Tatu Saloranta060ce112012-02-01 22:18:09 -0800154 if (df == null) {
155 throw new IllegalArgumentException("Can not pass null DeserializerFactory");
156 }
157 _factory = df;
158 _cache = (cache == null) ? new DeserializerCache() : cache;
159
160 _featureFlags = 0;
161 _config = null;
162 _injectableValues = null;
163 _view = null;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700164 _attributes = null;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800165 }
166
167 protected DeserializationContext(DeserializationContext src,
168 DeserializerFactory factory)
169 {
170 _cache = src._cache;
171 _factory = factory;
172
173 _config = src._config;
174 _featureFlags = src._featureFlags;
175 _view = src._view;
176 _parser = src._parser;
177 _injectableValues = src._injectableValues;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700178 _attributes = src._attributes;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800179 }
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700180
181 /**
182 * Constructor used for creating actual per-call instances.
183 */
Tatu Saloranta060ce112012-02-01 22:18:09 -0800184 protected DeserializationContext(DeserializationContext src,
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700185 DeserializationConfig config, JsonParser p,
Tatu Saloranta060ce112012-02-01 22:18:09 -0800186 InjectableValues injectableValues)
187 {
188 _cache = src._cache;
189 _factory = src._factory;
190
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800191 _config = config;
Tatu Salorantae3ae58e2012-01-28 23:08:16 -0800192 _featureFlags = config.getDeserializationFeatures();
Tatu Salorantab2d3c7d2012-01-27 21:41:48 -0800193 _view = config.getActiveView();
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700194 _parser = p;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800195 _injectableValues = injectableValues;
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700196 _attributes = config.getAttributes();
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800197 }
Tatu Saloranta9439a312013-03-02 13:13:09 -0800198
Tatu Saloranta23328aa2014-10-28 22:38:15 -0700199 /**
200 * Copy-constructor for use with <code>copy()</code> by {@link ObjectMapper#copy()}
201 */
202 protected DeserializationContext(DeserializationContext src) {
203 _cache = new DeserializerCache();
204 _factory = src._factory;
205
206 _config = src._config;
207 _featureFlags = src._featureFlags;
208 _view = src._view;
209 _injectableValues = null;
210 }
211
Tatu Saloranta9439a312013-03-02 13:13:09 -0800212 /*
213 /**********************************************************
214 /* DatabindContext implementation
215 /**********************************************************
216 */
217
218 @Override
219 public DeserializationConfig getConfig() { return _config; }
220
221 @Override
222 public final Class<?> getActiveView() { return _view; }
223
224 @Override
225 public final AnnotationIntrospector getAnnotationIntrospector() {
226 return _config.getAnnotationIntrospector();
227 }
228
229 @Override
230 public final TypeFactory getTypeFactory() {
231 return _config.getTypeFactory();
232 }
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700233
234 /*
235 /**********************************************************
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800236 /* Access to per-call state, like generic attributes (2.3+)
Tatu Saloranta2f26e6a2013-10-06 22:05:32 -0700237 /**********************************************************
238 */
239
240 @Override
241 public Object getAttribute(Object key) {
242 return _attributes.getAttribute(key);
243 }
244
245 @Override
246 public DeserializationContext setAttribute(Object key, Object value)
247 {
248 _attributes = _attributes.withPerCallAttribute(key, value);
249 return this;
250 }
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800251
252 /**
253 * Accessor to {@link JavaType} of currently contextualized
254 * {@link ContextualDeserializer}, if any.
255 * This is sometimes useful for generic {@link JsonDeserializer}s that
256 * do not get passed (or do not retain) type information when being
257 * constructed: happens for example for deserializers constructed
258 * from annotations.
259 *
260 * @since 2.5
261 *
262 * @return Type of {@link ContextualDeserializer} being contextualized,
263 * if process is on-going; null if not.
264 */
265 public JavaType getContextualType() {
266 return (_currentType == null) ? null : _currentType.value();
267 }
268
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800269 /*
270 /**********************************************************
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800271 /* Public API, config setting accessors
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800272 /**********************************************************
273 */
274
275 /**
Dmitry Katsuboe70c66f2012-09-03 16:00:30 +0200276 * Method for getting current {@link DeserializerFactory}.
277 */
278 public DeserializerFactory getFactory() {
279 return _factory;
280 }
Tatu Saloranta9439a312013-03-02 13:13:09 -0800281
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800282 /**
283 * Convenience method for checking whether specified on/off
284 * feature is enabled
285 */
Tatu9610aff2012-02-02 11:30:08 -0800286 public final boolean isEnabled(DeserializationFeature feat) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800287 /* 03-Dec-2010, tatu: minor shortcut; since this is called quite often,
288 * let's use a local copy of feature settings:
289 */
290 return (_featureFlags & feat.getMask()) != 0;
291 }
292
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800293 /**
Tatu Saloranta0ac36ba2013-08-21 18:08:51 -0700294 * "Bulk" access method for checking that all features specified by
295 * mask are enabled.
296 *
297 * @since 2.3
298 */
299 public final boolean hasDeserializationFeatures(int featureMask) {
300 return _config.hasDeserializationFeatures(featureMask);
301 }
302
303 /**
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800304 * Method for accessing the currently active parser.
305 * May be different from the outermost parser
306 * when content is buffered.
307 *<p>
308 * Use of this method is discouraged: if code has direct access
309 * to the active parser, that should be used instead.
310 */
311 public final JsonParser getParser() { return _parser; }
312
313 public final Object findInjectableValue(Object valueId,
314 BeanProperty forProperty, Object beanInstance)
315 {
316 if (_injectableValues == null) {
317 throw new IllegalStateException("No 'injectableValues' configured, can not inject value with id ["+valueId+"]");
318 }
319 return _injectableValues.findInjectableValue(valueId, this, forProperty, beanInstance);
320 }
Tatu Salorantab2d3c7d2012-01-27 21:41:48 -0800321
Tatu Saloranta060ce112012-02-01 22:18:09 -0800322 /**
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800323 * Convenience method for accessing the default Base64 encoding
324 * used for decoding base64 encoded binary content.
325 * Same as calling:
326 *<pre>
327 * getConfig().getBase64Variant();
328 *</pre>
329 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800330 public final Base64Variant getBase64Variant() {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800331 return _config.getBase64Variant();
332 }
333
Tatu Saloranta060ce112012-02-01 22:18:09 -0800334 /**
335 * Convenience method, functionally equivalent to:
336 *<pre>
337 * getConfig().getNodeFactory();
338 * </pre>
339 */
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800340 public final JsonNodeFactory getNodeFactory() {
341 return _config.getNodeFactory();
342 }
343
Tatu Saloranta060ce112012-02-01 22:18:09 -0800344 /**
Tatu Salorantae6faa452012-02-23 19:44:42 -0800345 * Method for accessing default Locale to use: convenience method for
346 *<pre>
347 * getConfig().getLocale();
348 *</pre>
Tatu Salorantaaa512742012-02-22 22:51:33 -0800349 */
350 public Locale getLocale() {
Tatu Salorantae6faa452012-02-23 19:44:42 -0800351 return _config.getLocale();
Tatu Salorantaaa512742012-02-22 22:51:33 -0800352 }
353
Tatu Salorantae6faa452012-02-23 19:44:42 -0800354 /**
355 * Method for accessing default TimeZone to use: convenience method for
356 *<pre>
357 * getConfig().getTimeZone();
358 *</pre>
359 */
Tatu Salorantaaa512742012-02-22 22:51:33 -0800360 public TimeZone getTimeZone() {
Tatu Salorantae6faa452012-02-23 19:44:42 -0800361 return _config.getTimeZone();
Tatu Salorantaaa512742012-02-22 22:51:33 -0800362 }
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700363
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800364 /*
365 /**********************************************************
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800366 /* Public API, pass-through to DeserializerCache
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800367 /**********************************************************
368 */
Tatuc3a73d02012-01-31 12:45:49 -0800369
Tatu Salorantaaf263c32013-10-24 16:18:50 -0700370 @Deprecated // since 2.3, use overloaded variant
371 public boolean hasValueDeserializerFor(JavaType type) {
372 return hasValueDeserializerFor(type, null);
373 }
374
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800375 /**
Tatu Saloranta060ce112012-02-01 22:18:09 -0800376 * Method for checking whether we could find a deserializer
377 * for given type.
Cowtowncodera2e27202014-11-25 17:07:52 -0800378 *
Tatu Salorantaaf263c32013-10-24 16:18:50 -0700379 * @param type
380 * @since 2.3
Tatu Saloranta060ce112012-02-01 22:18:09 -0800381 */
Tatu Salorantaaf263c32013-10-24 16:18:50 -0700382 public boolean hasValueDeserializerFor(JavaType type, AtomicReference<Throwable> cause) {
383 try {
384 return _cache.hasValueDeserializerFor(this, _factory, type);
385 } catch (JsonMappingException e) {
386 if (cause != null) {
387 cause.set(e);
388 }
389 } catch (RuntimeException e) {
390 if (cause == null) { // earlier behavior
391 throw e;
392 }
393 cause.set(e);
394 }
395 return false;
Tatu Saloranta060ce112012-02-01 22:18:09 -0800396 }
397
Tatu Saloranta060ce112012-02-01 22:18:09 -0800398 /**
Tatuc3a73d02012-01-31 12:45:49 -0800399 * Method for finding a value deserializer, and creating a contextual
400 * version if necessary, for value reached via specified property.
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800401 */
Tatuc3a73d02012-01-31 12:45:49 -0800402 @SuppressWarnings("unchecked")
403 public final JsonDeserializer<Object> findContextualValueDeserializer(JavaType type,
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700404 BeanProperty prop) throws JsonMappingException
Tatuc3a73d02012-01-31 12:45:49 -0800405 {
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700406 JsonDeserializer<Object> deser = _cache.findValueDeserializer(this, _factory, type);
Tatuc3a73d02012-01-31 12:45:49 -0800407 if (deser != null) {
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800408 deser = (JsonDeserializer<Object>) handleSecondaryContextualization(deser, prop, type);
Tatuc3a73d02012-01-31 12:45:49 -0800409 }
410 return deser;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800411 }
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700412
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800413 /**
Cowtowncodera2e27202014-11-25 17:07:52 -0800414 * Variant that will try to locate deserializer for current type, but without
415 * performing any contextualization (unlike {@link #findContextualValueDeserializer})
416 * or checking for need to create a {@link TypeDeserializer} (unlike
417 * {@link #findRootValueDeserializer(JavaType)}.
418 * This method is usually called from within {@link ResolvableDeserializer#resolve},
419 * and expectation is that caller then calls either
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800420 * {@link #handlePrimaryContextualization(JsonDeserializer, BeanProperty, JavaType)} or
421 * {@link #handleSecondaryContextualization(JsonDeserializer, BeanProperty, JavaType)} at a
Cowtowncodera2e27202014-11-25 17:07:52 -0800422 * later point, as necessary.
423 *
424 * @since 2.5
425 */
426 public final JsonDeserializer<Object> findNonContextualValueDeserializer(JavaType type)
427 throws JsonMappingException
428 {
429 return _cache.findValueDeserializer(this, _factory, type);
430 }
431
432 /**
Tatuc3a73d02012-01-31 12:45:49 -0800433 * Method for finding a deserializer for root-level value.
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800434 */
Tatuc3a73d02012-01-31 12:45:49 -0800435 @SuppressWarnings("unchecked")
Tatu Saloranta9b9d0432012-01-30 09:20:26 -0800436 public final JsonDeserializer<Object> findRootValueDeserializer(JavaType type)
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700437 throws JsonMappingException
Tatuc3a73d02012-01-31 12:45:49 -0800438 {
Tatu Saloranta060ce112012-02-01 22:18:09 -0800439 JsonDeserializer<Object> deser = _cache.findValueDeserializer(this,
440 _factory, type);
Tatuc3a73d02012-01-31 12:45:49 -0800441 if (deser == null) { // can this occur?
442 return null;
443 }
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800444 deser = (JsonDeserializer<Object>) handleSecondaryContextualization(deser, null, type);
Tatuc3a73d02012-01-31 12:45:49 -0800445 TypeDeserializer typeDeser = _factory.findTypeDeserializer(_config, type);
446 if (typeDeser != null) {
447 // important: contextualize to indicate this is for root value
448 typeDeser = typeDeser.forProperty(null);
449 return new TypeWrappedDeserializer(typeDeser, deser);
450 }
451 return deser;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800452 }
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800453
454 /**
455 * Convenience method, functionally same as:
456 *<pre>
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700457 * getDeserializerProvider().findKeyDeserializer(getConfig(), prop.getType(), prop);
Tatu Salorantae8dc6032012-01-23 22:43:26 -0800458 *</pre>
459 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800460 public final KeyDeserializer findKeyDeserializer(JavaType keyType,
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700461 BeanProperty prop) throws JsonMappingException {
Tatu Saloranta060ce112012-02-01 22:18:09 -0800462 KeyDeserializer kd = _cache.findKeyDeserializer(this,
463 _factory, keyType);
Tatud0bb3152012-01-31 13:04:06 -0800464 // Second: contextualize?
465 if (kd instanceof ContextualKeyDeserializer) {
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700466 kd = ((ContextualKeyDeserializer) kd).createContextual(this, prop);
Tatud0bb3152012-01-31 13:04:06 -0800467 }
468 return kd;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800469 }
470
Tatub37ff332012-01-24 16:19:36 -0800471 /*
472 /**********************************************************
Tatu Saloranta34a8adf2012-02-08 22:07:36 -0800473 /* Public API, ObjectId handling
474 /**********************************************************
475 */
476
477 /**
478 * Method called to find and return entry corresponding to given
479 * Object Id: will add an entry if necessary, and never returns null
480 */
Pascal GĂ©linas184cae32014-02-05 17:35:56 -0500481 public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> generator, ObjectIdResolver resolver);
482
Tatu Saloranta301ea2d2014-03-16 22:26:12 -0700483 @Deprecated // since 2.4
Pascal GĂ©linas184cae32014-02-05 17:35:56 -0500484 public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> generator);
Tatu Salorantabf5e0fa2012-03-08 21:45:30 -0800485
Pascal GĂ©linas096e02b2013-12-18 17:21:42 -0500486 /**
487 * Method called to ensure that every object id encounter during processing
488 * are resolved.
489 *
490 * @throws UnresolvedForwardReference
491 */
492 public abstract void checkUnresolvedObjectId()
493 throws UnresolvedForwardReference;
494
Tatu Salorantabf5e0fa2012-03-08 21:45:30 -0800495 /*
496 /**********************************************************
497 /* Public API, type handling
498 /**********************************************************
499 */
500
501 /**
502 * Convenience method, functionally equivalent to:
503 *<pre>
504 * getConfig().constructType(cls);
505 * </pre>
506 */
507 public final JavaType constructType(Class<?> cls) {
508 return _config.constructType(cls);
509 }
510
511 /**
512 * Helper method to use for locating Class for given name. Should be used
513 * instead of basic <code>Class.forName(className);</code> as it can
514 * try using contextual class loader, or use platform-specific workarounds
515 * (like on Android, GAE).
516 */
517 public Class<?> findClass(String className) throws ClassNotFoundException
518 {
519 // By default, delegate to ClassUtil: can be overridden with custom handling
520 return ClassUtil.findClass(className);
521 }
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800522
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800523 /*
524 /**********************************************************
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800525 /* Public API, helper object recycling
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800526 /**********************************************************
527 */
528
529 /**
530 * Method that can be used to get access to a reusable ObjectBuffer,
531 * useful for efficiently constructing Object arrays and Lists.
532 * Note that leased buffers should be returned once deserializer
533 * is done, to allow for reuse during same round of deserialization.
534 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800535 public final ObjectBuffer leaseObjectBuffer()
536 {
537 ObjectBuffer buf = _objectBuffer;
538 if (buf == null) {
539 buf = new ObjectBuffer();
540 } else {
541 _objectBuffer = null;
542 }
543 return buf;
544 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800545
546 /**
547 * Method to call to return object buffer previously leased with
548 * {@link #leaseObjectBuffer}.
549 *
550 * @param buf Returned object buffer
551 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800552 public final void returnObjectBuffer(ObjectBuffer buf)
553 {
554 /* Already have a reusable buffer? Let's retain bigger one
555 * (or if equal, favor newer one, shorter life-cycle)
556 */
557 if (_objectBuffer == null
558 || buf.initialCapacity() >= _objectBuffer.initialCapacity()) {
559 _objectBuffer = buf;
560 }
561 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800562
563 /**
564 * Method for accessing object useful for building arrays of
565 * primitive types (such as int[]).
566 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800567 public final ArrayBuilders getArrayBuilders()
568 {
569 if (_arrayBuilders == null) {
570 _arrayBuilders = new ArrayBuilders();
571 }
572 return _arrayBuilders;
573 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800574
575 /*
576 /**********************************************************
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700577 /* Extended API: handler instantiation
578 /**********************************************************
579 */
580
581 public abstract JsonDeserializer<Object> deserializerInstance(Annotated annotated,
582 Object deserDef)
583 throws JsonMappingException;
584
585 public abstract KeyDeserializer keyDeserializerInstance(Annotated annotated,
586 Object deserDef)
587 throws JsonMappingException;
588
589 /*
590 /**********************************************************
591 /* Extended API: resolving contextual deserializers; called
592 /* by structured deserializers for their value/component
593 /* deserializers
594 /**********************************************************
595 */
596
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700597 /**
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700598 * Method called for primary property deserializers (ones
Tatu Saloranta59fe29c2013-09-05 22:37:06 -0700599 * directly created to deserialize values of a POJO property),
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700600 * to handle details of resolving
601 * {@link ContextualDeserializer} with given property context.
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700602 *
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700603 * @param prop Property for which the given primary deserializer is used; never null.
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700604 *
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800605 * @since 2.5
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700606 */
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700607 public JsonDeserializer<?> handlePrimaryContextualization(JsonDeserializer<?> deser,
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800608 BeanProperty prop, JavaType type)
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700609 throws JsonMappingException
610 {
Cowtowncodera2e27202014-11-25 17:07:52 -0800611 if (deser instanceof ContextualDeserializer) {
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800612 _currentType = new LinkedNode<JavaType>(type, _currentType);
613 try {
614 deser = ((ContextualDeserializer) deser).createContextual(this, prop);
615 } finally {
616 _currentType = _currentType.next();
617 }
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700618 }
619 return deser;
620 }
Tatu Salorantab530c4d2013-09-04 22:20:13 -0700621
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700622 /**
623 * Method called for secondary property deserializers (ones
624 * NOT directly created to deal with an annotatable POJO property,
625 * but instead created as a component -- such as value deserializers
626 * for structured types, or deserializers for root values)
627 * to handle details of resolving
628 * {@link ContextualDeserializer} with given property context.
Tatu Saloranta59fe29c2013-09-05 22:37:06 -0700629 * Given that these deserializers are not directly related to given property
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700630 * (or, in case of root value property, to any property), annotations
631 * accessible may or may not be relevant.
632 *
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700633 * @param prop Property for which deserializer is used, if any; null
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700634 * when deserializing root values
635 *
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800636 * @since 2.5
Tatu Saloranta4f90dbc2013-09-05 21:45:53 -0700637 */
638 public JsonDeserializer<?> handleSecondaryContextualization(JsonDeserializer<?> deser,
Tatu Salorantac4b6c612014-12-26 22:07:54 -0800639 BeanProperty prop, JavaType type)
640 throws JsonMappingException
641 {
642 if (deser instanceof ContextualDeserializer) {
643 _currentType = new LinkedNode<JavaType>(type, _currentType);
644 try {
645 deser = ((ContextualDeserializer) deser).createContextual(this, prop);
646 } finally {
647 _currentType = _currentType.next();
648 }
649 }
650 return deser;
651 }
652
Cowtowncoder36864212015-03-16 14:23:22 -0700653 @Deprecated // since 2.5; remove from 2.7
654 public JsonDeserializer<?> handlePrimaryContextualization(JsonDeserializer<?> deser, BeanProperty prop) throws JsonMappingException {
655 return handlePrimaryContextualization(deser, prop, TypeFactory.unknownType());
656 }
657
658 @Deprecated // since 2.5; remove from 2.7
659 public JsonDeserializer<?> handleSecondaryContextualization(JsonDeserializer<?> deser, BeanProperty prop) throws JsonMappingException {
660 if (deser instanceof ContextualDeserializer) {
661 deser = ((ContextualDeserializer) deser).createContextual(this, prop);
662 }
663 return deser;
664 }
665
Tatu Salorantaf72fe212013-09-04 22:07:32 -0700666 /*
667 /**********************************************************
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800668 /* Parsing methods that may use reusable/-cyclable objects
669 /**********************************************************
670 */
671
672 /**
673 * Convenience method for parsing a Date from given String, using
674 * currently configured date format (accessed using
675 * {@link DeserializationConfig#getDateFormat()}).
676 *<p>
677 * Implementation will handle thread-safety issues related to
678 * date formats such that first time this method is called,
679 * date format is cloned, and cloned instance will be retained
680 * for use during this deserialization round.
681 */
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700682 public Date parseDate(String dateStr) throws IllegalArgumentException
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800683 {
684 try {
Tatu Salorantaef00ac62013-11-03 09:56:39 -0800685 DateFormat df = getDateFormat();
686 return df.parse(dateStr);
Tatu Salorantaaa512742012-02-22 22:51:33 -0800687 } catch (ParseException e) {
688 throw new IllegalArgumentException("Failed to parse Date value '"+dateStr+"': "+e.getMessage());
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800689 }
690 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800691
692 /**
693 * Convenience method for constructing Calendar instance set
694 * to specified time, to be modified and used by caller.
695 */
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700696 public Calendar constructCalendar(Date d) {
697 // 08-Jan-2008, tatu: not optimal, but should work for the most part; let's revise as needed.
Tatu Salorantaaa512742012-02-22 22:51:33 -0800698 Calendar c = Calendar.getInstance(getTimeZone());
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800699 c.setTime(d);
700 return c;
701 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800702
703 /*
704 /**********************************************************
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700705 /* Convenience methods for reading parsed values
706 /**********************************************************
707 */
708
709 /**
710 * Convenience method that may be used by composite or container deserializers,
711 * for reading one-off values contained (for sequences, it is more efficient
712 * to actually fetch deserializer once for the whole collection).
713 *<p>
714 * NOTE: when deserializing values of properties contained in composite types,
715 * rather use {@link #readPropertyValue(JsonParser, BeanProperty, Class)};
716 * this method does not allow use of contextual annotations.
717 *
718 * @since 2.4
719 */
720 public <T> T readValue(JsonParser p, Class<T> type) throws IOException {
721 return readValue(p, getTypeFactory().constructType(type));
722 }
723
724 /**
725 * @since 2.4
726 */
727 @SuppressWarnings("unchecked")
728 public <T> T readValue(JsonParser p, JavaType type) throws IOException {
729 JsonDeserializer<Object> deser = findRootValueDeserializer(type);
730 if (deser == null) {
731 }
732 return (T) deser.deserialize(p, this);
733 }
734
735 /**
736 * Convenience method that may be used by composite or container deserializers,
737 * for reading one-off values for the composite type, taking into account
738 * annotations that the property (passed to this method -- usually property that
739 * has custom serializer that called this method) has.
740 *
741 * @since 2.4
742 */
743 public <T> T readPropertyValue(JsonParser p, BeanProperty prop, Class<T> type) throws IOException {
744 return readPropertyValue(p, prop, getTypeFactory().constructType(type));
745 }
746
747 /**
748 * @since 2.4
749 */
750 @SuppressWarnings("unchecked")
751 public <T> T readPropertyValue(JsonParser p, BeanProperty prop, JavaType type) throws IOException {
752 JsonDeserializer<Object> deser = findContextualValueDeserializer(type, prop);
753 if (deser == null) {
754
755 }
756 return (T) deser.deserialize(p, this);
757 }
758
759 /*
760 /**********************************************************
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800761 /* Methods for problem handling, reporting
762 /**********************************************************
763 */
764
765 /**
766 * Method deserializers can call to inform configured {@link DeserializationProblemHandler}s
767 * of an unrecognized property.
768 *
769 * @return True if there was a configured problem handler that was able to handle the
Tatu Saloranta0e3b3832012-01-22 22:08:20 -0800770 * problem
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800771 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800772 /**
773 * Method deserializers can call to inform configured {@link DeserializationProblemHandler}s
774 * of an unrecognized property.
775 */
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700776 public boolean handleUnknownProperty(JsonParser p, JsonDeserializer<?> deser,
Tatu Saloranta060ce112012-02-01 22:18:09 -0800777 Object instanceOrClass, String propName)
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800778 throws IOException, JsonProcessingException
779 {
780 LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
781 if (h != null) {
Tatu Saloranta060ce112012-02-01 22:18:09 -0800782 while (h != null) {
783 // Can bail out if it's handled
Tatu Saloranta478d4a42014-03-16 21:53:33 -0700784 if (h.value().handleUnknownProperty(this, p, deser, instanceOrClass, propName)) {
Tatu Saloranta060ce112012-02-01 22:18:09 -0800785 return true;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800786 }
Tatu Saloranta060ce112012-02-01 22:18:09 -0800787 h = h.next();
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800788 }
789 }
790 return false;
791 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800792
793 /**
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800794 * Helper method for reporting a problem with unhandled unknown exception
795 *
796 * @param instanceOrClass Either value being populated (if one has been
797 * instantiated), or Class that indicates type that would be (or
798 * have been) instantiated
Tatu Saloranta05fce932012-03-19 17:14:05 -0700799 * @param deser Deserializer that had the problem, if called by deserializer
800 * (or on behalf of one)
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800801 */
Tatu Saloranta05fce932012-03-19 17:14:05 -0700802 public void reportUnknownProperty(Object instanceOrClass, String fieldName,
803 JsonDeserializer<?> deser)
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800804 throws JsonMappingException
805 {
Tatu Saloranta05fce932012-03-19 17:14:05 -0700806 if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
807 return;
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800808 }
Tatu Saloranta05fce932012-03-19 17:14:05 -0700809 // Do we know properties that are expected instead?
810 Collection<Object> propIds = (deser == null) ? null : deser.getKnownPropertyNames();
811 throw UnrecognizedPropertyException.from(_parser,
812 instanceOrClass, fieldName, propIds);
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800813 }
814
815 /*
816 /**********************************************************
817 /* Methods for constructing exceptions
818 /**********************************************************
819 */
820
821 /**
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800822 * Helper method for constructing generic mapping exception for specified type
823 */
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800824 public JsonMappingException mappingException(Class<?> targetClass) {
825 return mappingException(targetClass, _parser.getCurrentToken());
826 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800827
Tatu Saloranta80e1b7e2014-01-11 20:11:33 -0800828 public JsonMappingException mappingException(Class<?> targetClass, JsonToken token) {
829 return JsonMappingException.from(_parser, "Can not deserialize instance of "+_calcName(targetClass)+" out of "+token+" token");
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800830 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800831
832 /**
833 * Helper method for constructing generic mapping exception with specified
834 * message and current location information
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800835 */
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800836 public JsonMappingException mappingException(String message) {
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800837 return JsonMappingException.from(getParser(), message);
838 }
839
840 /**
841 * Helper method for constructing instantiation exception for specified type,
842 * to indicate problem with physically constructing instance of
843 * specified class (missing constructor, exception from constructor)
844 */
Tatu Saloranta80e1b7e2014-01-11 20:11:33 -0800845 public JsonMappingException instantiationException(Class<?> instClass, Throwable t) {
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800846 return JsonMappingException.from(_parser,
Tatu Saloranta80e1b7e2014-01-11 20:11:33 -0800847 "Can not construct instance of "+instClass.getName()+", problem: "+t.getMessage(), t);
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800848 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800849
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800850 public JsonMappingException instantiationException(Class<?> instClass, String msg) {
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800851 return JsonMappingException.from(_parser, "Can not construct instance of "+instClass.getName()+", problem: "+msg);
852 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800853
854 /**
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800855 * Method that will construct an exception suitable for throwing when
856 * some String values are acceptable, but the one encountered is not.
Tatu Salorantadd348562012-07-18 17:25:02 -0700857 *
858 *
859 * @deprecated Since 2.1 should use variant that takes value
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800860 */
Tatu Salorantadd348562012-07-18 17:25:02 -0700861 @Deprecated
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800862 public JsonMappingException weirdStringException(Class<?> instClass, String msg) {
Tatu Salorantadd348562012-07-18 17:25:02 -0700863 return weirdStringException(null, instClass, msg);
864 }
865
866 /**
867 * Method that will construct an exception suitable for throwing when
868 * some String values are acceptable, but the one encountered is not.
869 *
870 * @param value String value from input being deserialized
871 * @param instClass Type that String should be deserialized into
872 * @param msg Message that describes specific problem
873 *
874 * @since 2.1
875 */
876 public JsonMappingException weirdStringException(String value, Class<?> instClass, String msg) {
877 return InvalidFormatException.from(_parser,
878 "Can not construct instance of "+instClass.getName()+" from String value '"+_valueDesc()+"': "+msg,
879 value, instClass);
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800880 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800881
882 /**
883 * Helper method for constructing exception to indicate that input JSON
884 * Number was not suitable for deserializing into given type.
885 */
Tatu Salorantadd348562012-07-18 17:25:02 -0700886 @Deprecated
Tatu Saloranta2fd4ffd2012-02-17 22:40:13 -0800887 public JsonMappingException weirdNumberException(Class<?> instClass, String msg) {
Tatu Salorantadd348562012-07-18 17:25:02 -0700888 return weirdStringException(null, instClass, msg);
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800889 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800890
891 /**
Tatu Salorantadd348562012-07-18 17:25:02 -0700892 * Helper method for constructing exception to indicate that input JSON
893 * Number was not suitable for deserializing into given target type.
894 */
895 public JsonMappingException weirdNumberException(Number value, Class<?> instClass, String msg) {
896 return InvalidFormatException.from(_parser,
897 "Can not construct instance of "+instClass.getName()+" from number value ("+_valueDesc()+"): "+msg,
898 null, instClass);
899 }
900
901 /**
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800902 * Helper method for constructing exception to indicate that given JSON
903 * Object field name was not in format to be able to deserialize specified
904 * key type.
905 */
Tatu Saloranta80e1b7e2014-01-11 20:11:33 -0800906 public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue, String msg) {
Tatu Salorantadd348562012-07-18 17:25:02 -0700907 return InvalidFormatException.from(_parser,
908 "Can not construct Map key of type "+keyClass.getName()+" from String \""+_desc(keyValue)+"\": "+msg,
909 keyValue, keyClass);
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800910 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800911
912 /**
913 * Helper method for indicating that the current token was expected to be another
914 * token.
915 */
Tatu Saloranta953eab22014-05-15 21:35:28 -0700916 public JsonMappingException wrongTokenException(JsonParser p, JsonToken expToken, String msg0) {
917 String msg = "Unexpected token ("+p.getCurrentToken()+"), expected "+expToken;
918 if (msg0 != null) {
919 msg = msg + ": "+msg0;
920 }
921 return JsonMappingException.from(p, msg);
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800922 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800923
924 /**
925 * Helper method for constructing exception to indicate that given
926 * type id (parsed from JSON) could not be converted to a Java type.
Tatu Salorantae4f23bb2011-12-23 00:31:35 -0800927 */
Tatu Saloranta7fc32382014-12-26 17:19:09 -0800928 @Deprecated // since 2.5, use overloaded variant
Tatu Saloranta80e1b7e2014-01-11 20:11:33 -0800929 public JsonMappingException unknownTypeException(JavaType type, String id) {
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800930 return JsonMappingException.from(_parser, "Could not resolve type id '"+id+"' into a subtype of "+type);
931 }
932
Tatu Saloranta7fc32382014-12-26 17:19:09 -0800933 /**
934 * @since 2.5
935 */
936 public JsonMappingException unknownTypeException(JavaType type, String id,
937 String extraDesc) {
938 String msg = "Could not resolve type id '"+id+"' into a subtype of "+type;
939 if (extraDesc != null) {
940 msg = msg + ": "+extraDesc;
941 }
942 return JsonMappingException.from(_parser, msg);
943 }
944
Tatu Saloranta80e1b7e2014-01-11 20:11:33 -0800945 public JsonMappingException endOfInputException(Class<?> instClass) {
Tatu Saloranta5bd18092012-09-14 20:19:43 -0700946 return JsonMappingException.from(_parser, "Unexpected end-of-input when trying to deserialize a "
947 +instClass.getName());
948 }
Tatu Saloranta7fc32382014-12-26 17:19:09 -0800949
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800950 /*
951 /**********************************************************
952 /* Overridable internal methods
953 /**********************************************************
954 */
955
956 protected DateFormat getDateFormat()
957 {
Tatu Saloranta3b88a6b2012-02-24 09:53:59 -0800958 if (_dateFormat != null) {
959 return _dateFormat;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800960 }
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -0800961 /* 24-Feb-2012, tatu: At this point, all timezone configuration
Cowtowncoder8d0d6e42015-01-22 15:36:13 -0800962 * should have occurred, with respect to default dateformat
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -0800963 * and timezone configuration. But we still better clone
964 * an instance as formatters may be stateful.
Tatu Saloranta3b88a6b2012-02-24 09:53:59 -0800965 */
966 DateFormat df = _config.getDateFormat();
Tatu Saloranta3f0ca2e2012-02-25 15:54:08 -0800967 _dateFormat = df = (DateFormat) df.clone();
Tatu Saloranta3b88a6b2012-02-24 09:53:59 -0800968 return df;
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800969 }
970
Tatu Saloranta80e1b7e2014-01-11 20:11:33 -0800971 protected String determineClassName(Object instance) {
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800972 return ClassUtil.getClassDescription(instance);
973 }
974
975 /*
976 /**********************************************************
977 /* Other internal methods
978 /**********************************************************
979 */
980
Tatu Saloranta80e1b7e2014-01-11 20:11:33 -0800981 protected String _calcName(Class<?> cls) {
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800982 if (cls.isArray()) {
983 return _calcName(cls.getComponentType())+"[]";
984 }
985 return cls.getName();
986 }
987
Tatu Saloranta80e1b7e2014-01-11 20:11:33 -0800988 protected String _valueDesc() {
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800989 try {
990 return _desc(_parser.getText());
991 } catch (Exception e) {
992 return "[N/A]";
993 }
994 }
Tatu Saloranta80e1b7e2014-01-11 20:11:33 -0800995
996 protected String _desc(String desc) {
Tatu Saloranta06c20b12012-01-29 21:36:52 -0800997 // !!! should we quote it? (in case there are control chars, linefeeds)
998 if (desc.length() > MAX_ERROR_STR_LEN) {
999 desc = desc.substring(0, MAX_ERROR_STR_LEN) + "]...[" + desc.substring(desc.length() - MAX_ERROR_STR_LEN);
1000 }
1001 return desc;
1002 }
Tatu Salorantae4f23bb2011-12-23 00:31:35 -08001003}