Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.codehaus.jackson.map.deser.BeanDeserializer Maven / Gradle / Ivy
Go to download
Data Mapper package is a high-performance data binding package
built on Jackson JSON processor
package org.codehaus.jackson.map.deser;
import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;
import org.codehaus.jackson.*;
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.map.annotate.JsonCachable;
import org.codehaus.jackson.map.type.ClassKey;
import org.codehaus.jackson.map.type.TypeFactory;
import org.codehaus.jackson.map.util.ClassUtil;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.util.TokenBuffer;
/**
* Deserializer class that can deserialize instances of
* arbitrary bean objects, usually from JSON Object structs,
* but possibly also from simple types like String values.
*/
@JsonCachable
/* Because of costs associated with constructing bean deserializers,
* they usually should be cached unlike other deserializer types.
* But more importantly, it is important to be able to cache
* bean serializers to handle cyclic references.
*/
public class BeanDeserializer
extends StdDeserializer
implements ResolvableDeserializer
{
/*
/**********************************************************
/* Information regarding type being deserialized
/**********************************************************
*/
/**
* Declared type of the bean this deserializer handles.
*/
final protected JavaType _beanType;
/*
/**********************************************************
/* Construction configuration
/**********************************************************
*/
/**
* Default constructor used to instantiate the bean when mapping
* from Json object, and only using setters for initialization
* (not specific constructors).
*
* Note: may be null, if deserializer is constructed for abstract
* types (which is only useful if additional type information will
* allow construction of concrete subtype).
*/
protected Constructor> _defaultConstructor;
/**
* If the "bean" class can be instantiated using just a single
* String (via constructor, static method etc), this object
* knows how to invoke method/constructor in question.
* If so, no setters will be used.
*/
protected Creator.StringBased _stringCreator;
/**
* If the "bean" class can be instantiated using just a single
* numeric (int, long) value (via constructor, static method etc),
* this object
* knows how to invoke method/constructor in question.
* If so, no setters will be used.
*/
protected Creator.NumberBased _numberCreator;
/**
* If the bean class can be instantiated using a creator
* (an annotated single arg constructor or static method),
* this object is used for handling details of how delegate-based
* deserialization and instance construction works
*/
protected Creator.Delegating _delegatingCreator;
/**
* If the bean needs to be instantiated using constructor
* or factory method
* that takes one or more named properties as argument(s),
* this creator is used for instantiation.
*/
protected Creator.PropertyBased _propertyBasedCreator;
/*
/**********************************************************
/* Property information, setters
/**********************************************************
*/
/**
* Things set via setters (modifiers) are included in this
* Map.
*/
final protected HashMap _props;
/**
* Fallback setter used for handling any properties that are not
* mapped to regular setters. If setter is not null, it will be
* called once for each such property.
*/
protected SettableAnyProperty _anySetter;
/**
* In addition to properties that are set, we will also keep
* track of recognized but ignorable properties: these will
* be skipped without errors or warnings.
*/
protected HashSet _ignorableProps;
/**
* Flag that can be set to ignore and skip unknown properties.
* If set, will not throw an exception for unknown properties.
*/
protected boolean _ignoreAllUnknown;
/**
* We may also have one or more back reference fields (usually
* zero or one).
*/
protected HashMap _backRefs;
/*
/**********************************************************
/* Special deserializers needed for sub-types
/**********************************************************
*/
/**
* Lazily constructed map used to contain deserializers needed
* for polymorphic subtypes.
*/
protected HashMap> _subDeserializers;
/*
/**********************************************************
/* Life-cycle, construction, initialization
/**********************************************************
*/
public BeanDeserializer(JavaType type)
{
super(type.getRawClass());
_beanType = type;
_props = new HashMap();
_ignorableProps = null;
}
public void setDefaultConstructor(Constructor> ctor) {
_defaultConstructor = ctor;
}
/**
* Method called by factory after it has introspected all available
* Creators (constructors, static factory methods).
*/
public void setCreators(CreatorContainer creators)
{
_stringCreator = creators.stringCreator();
_numberCreator = creators.numberCreator();
/* Delegating constructor means that
* the JSON Object is first deserialized into delegated type, and
* then resulting value is passed as the argument to delegating
* constructor.
*
* Note that delegating constructors have precedence over default
* and property-based constructors.
*/
_delegatingCreator = creators.delegatingCreator();
_propertyBasedCreator = creators.propertyBasedCreator();
/* important: ensure we do not hold on to default constructor,
* if delegating OR property-based creator is found
*/
if (_delegatingCreator != null || _propertyBasedCreator != null) {
_defaultConstructor = null;
}
}
/**
* Method to add a property setter. Will ensure that there is no
* unexpected override; if one is found will throw a
* {@link IllegalArgumentException}.
*/
public void addProperty(SettableBeanProperty prop)
{
SettableBeanProperty old = _props.put(prop.getPropertyName(), prop);
if (old != null && old != prop) { // should never occur...
throw new IllegalArgumentException("Duplicate property '"+prop.getPropertyName()+"' for "+_beanType);
}
}
/**
* @since 1.6
*/
public boolean hasProperty(String propertyName) {
return _props.containsKey(propertyName);
}
public void addBackReferenceProperty(String referenceName, SettableBeanProperty prop)
{
if (_backRefs == null) {
_backRefs = new HashMap(4);
}
_backRefs.put(referenceName, prop);
}
public SettableBeanProperty removeProperty(String name)
{
return _props.remove(name);
}
public void setAnySetter(SettableAnyProperty s)
{
if (_anySetter != null && s != null) {
throw new IllegalStateException("_anySetter already set to non-null");
}
_anySetter = s;
}
public void setIgnoreUnknownProperties(boolean ignore) {
_ignoreAllUnknown = ignore;
}
/**
* Method that will add property name as one of properties that can
* be ignored if not recognized.
*/
public void addIgnorable(String propName)
{
if (_ignorableProps == null) {
_ignorableProps = new HashSet();
}
_ignorableProps.add(propName);
}
/*
/**********************************************************
/* Validation, post-processing
/**********************************************************
*/
/**
* Method called to finalize setup of this deserializer,
* after deserializer itself has been registered. This
* is needed to handle recursive and transitive dependencies.
*/
public void resolve(DeserializationConfig config, DeserializerProvider provider)
throws JsonMappingException
{
// let's reuse same instances, not all are cached by provider
/* 04-Feb-2009, tatu: This is tricky now that we are to pass referrer
* information, as there is no easy+reliable+efficient way to do
* it. But we can use a quick heuristic: only cache "expensive"
* BeanDeserializers; for them it is unlikely that different
* references should lead to different deserializers, and for other
* types cost is much lower so we can drop caching
*/
HashMap> seen = new HashMap>();
for (Map.Entry en : _props.entrySet()) {
SettableBeanProperty prop = en.getValue();
// May already have deserializer from annotations, if so, skip:
if (!prop.hasValueDeserializer()) {
prop.setValueDeserializer(findDeserializer(config, provider, prop.getType(), prop.getPropertyName(), seen));
}
// and for [JACKSON-235] need to finally link managed references with matching back references
String refName = prop.getManagedReferenceName();
if (refName != null) {
JsonDeserializer> valueDeser = prop._valueDeserializer;
SettableBeanProperty backProp = null;
boolean isContainer = false;
if (valueDeser instanceof BeanDeserializer) {
backProp = ((BeanDeserializer) valueDeser).findBackReference(refName);
} else if (valueDeser instanceof ContainerDeserializer>) {
JsonDeserializer> contentDeser = ((ContainerDeserializer>) valueDeser).getContentDeserializer();
if (!(contentDeser instanceof BeanDeserializer)) {
throw new IllegalArgumentException("Can not handle managed/back reference '"+refName
+"': value deserializer is of type ContainerDeserializer, but content type is not handled by a BeanDeserializer "
+" (instead it's of type "+contentDeser.getClass().getName()+")");
}
backProp = ((BeanDeserializer) contentDeser).findBackReference(refName);
isContainer = true;
} else if (valueDeser instanceof AbstractDeserializer) { // [JACKSON-368]: not easy to fix, alas
throw new IllegalArgumentException("Can not handle managed/back reference for abstract types (property "+_beanType.getRawClass().getName()+"."+prop.getPropertyName()+")");
} else {
throw new IllegalArgumentException("Can not handle managed/back reference '"+refName
+"': type for value deserializer is not BeanDeserializer or ContainerDeserializer, but "
+valueDeser.getClass().getName());
}
if (backProp == null) {
throw new IllegalArgumentException("Can not handle managed/back reference '"+refName+"': no back reference property found from type "
+prop.getType());
}
// also: verify that type is compatible
JavaType referredType = _beanType;
JavaType backRefType = backProp.getType();
if (!backRefType.getRawClass().isAssignableFrom(referredType.getRawClass())) {
throw new IllegalArgumentException("Can not handle managed/back reference '"+refName+"': back reference type ("
+backRefType.getRawClass().getName()+") not compatible with managed type ("
+referredType.getRawClass().getName()+")");
}
en.setValue(new SettableBeanProperty.ManagedReferenceProperty(refName, prop, backProp, isContainer));
}
}
// Finally, "any setter" may also need to be resolved now
if (_anySetter != null && !_anySetter.hasValueDeserializer()) {
_anySetter.setValueDeserializer(findDeserializer(config, provider, _anySetter.getType(), "[any]", seen));
}
// as well as delegate-based constructor:
if (_delegatingCreator != null) {
JsonDeserializer deser = findDeserializer(config, provider, _delegatingCreator.getValueType(), "[constructor-arg[0]]", seen);
_delegatingCreator.setDeserializer(deser);
}
// or property-based one
if (_propertyBasedCreator != null) {
for (SettableBeanProperty prop : _propertyBasedCreator.properties()) {
if (!prop.hasValueDeserializer()) {
prop.setValueDeserializer(findDeserializer(config, provider, prop.getType(), prop.getPropertyName(), seen));
}
}
}
}
/*
/**********************************************************
/* JsonDeserializer implementation
/**********************************************************
*/
/**
* Main deserialization method for bean-based objects (POJOs).
*/
@Override
public final Object deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
// common case first:
if (t == JsonToken.START_OBJECT) {
jp.nextToken();
return deserializeFromObject(jp, ctxt);
}
// and then others, generally requiring use of @JsonCreator
switch (t) {
case VALUE_STRING:
return deserializeFromString(jp, ctxt);
case VALUE_NUMBER_INT:
case VALUE_NUMBER_FLOAT:
return deserializeFromNumber(jp, ctxt);
case VALUE_EMBEDDED_OBJECT:
return jp.getEmbeddedObject();
case VALUE_TRUE:
case VALUE_FALSE:
case START_ARRAY:
// these only work if there's a (delegating) creator...
return deserializeUsingCreator(jp, ctxt);
case FIELD_NAME:
case END_OBJECT: // added to resolve [JACKSON-319], possible related issues
return deserializeFromObject(jp, ctxt);
}
throw ctxt.mappingException(getBeanClass());
}
/**
* Secondary deserialization method, called in cases where POJO
* instance is created as part of deserialization, potentially
* after collecting some or all of the properties to set.
*/
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt, Object bean)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
// 23-Mar-2010, tatu: In some cases, we start with full JSON object too...
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
SettableBeanProperty prop = _props.get(propName);
jp.nextToken(); // skip field, returns value token
if (prop != null) { // normal case
try {
prop.deserializeAndSet(jp, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName);
}
continue;
}
/* As per [JACKSON-313], things marked as ignorable should not be
* passed to any setter
*/
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
jp.skipChildren();
continue;
}
if (_anySetter != null) {
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
continue;
}
// Unknown: let's call handler method
handleUnknownProperty(jp, ctxt, bean, propName);
}
return bean;
}
@Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
TypeDeserializer typeDeserializer)
throws IOException, JsonProcessingException
{
// In future could check current token... for now this should be enough:
return typeDeserializer.deserializeTypedFromObject(jp, ctxt);
}
/*
/**********************************************************
/* Other public accessors
/**********************************************************
*/
public final Class> getBeanClass() { return _beanType.getRawClass(); }
@Override public JavaType getValueType() { return _beanType; }
/**
* @since 1.6
*/
public Iterable properties() {
return _props.values();
}
/**
* Method needed by {@link BeanDeserializerFactory} to properly link
* managed- and back-reference pairs.
*/
public SettableBeanProperty findBackReference(String logicalName)
{
if (_backRefs == null) {
return null;
}
return _backRefs.get(logicalName);
}
/*
/**********************************************************
/* Concrete deserialization methods
/**********************************************************
*/
public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_defaultConstructor == null) {
// 25-Jul-2009, tatu: finally, can also use "non-default" constructor (or factory method)
if (_propertyBasedCreator != null) {
return _deserializeUsingPropertyBased(jp, ctxt);
}
// 07-Jul-2009, tatu: let's allow delegate-based approach too
if (_delegatingCreator != null) {
return _delegatingCreator.deserialize(jp, ctxt);
}
// should only occur for abstract types...
if (_beanType.isAbstract()) {
throw JsonMappingException.from(jp, "Can not instantiate abstract type "+_beanType
+" (need to add/enable type information?)");
}
throw JsonMappingException.from(jp, "No suitable constructor found for type "+_beanType+": can not instantiate from JSON object (need to add/enable type information?)");
}
Object bean;
try {
bean = _defaultConstructor.newInstance();
} catch (Exception e) {
ClassUtil.unwrapAndThrowAsIAE(e);
return null; // never gets here
}
for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) {
String propName = jp.getCurrentName();
// Skip field name:
jp.nextToken();
SettableBeanProperty prop = _props.get(propName);
if (prop != null) { // normal case
// As per [JACKSON-397], should NOT catch and rethrow for 1.6.1 (1.6.0 didn't), need to wait until 1.7.0
//try {
prop.deserializeAndSet(jp, ctxt, bean);
//} catch (Exception e) {
// wrapAndThrow(e, bean, propName);
//}
continue;
}
/* As per [JACKSON-313], things marked as ignorable should not be
* passed to any setter
*/
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
jp.skipChildren();
continue;
}
if (_anySetter != null) {
// As per [JACKSON-397], should NOT catch and rethrow for 1.6.1 (1.6.0 didn't), need to wait until 1.7.0
//try {
_anySetter.deserializeAndSet(jp, ctxt, bean, propName);
//} catch (Exception e) {
// wrapAndThrow(e, bean, propName);
//}
continue;
}
// Unknown: let's call handler method
handleUnknownProperty(jp, ctxt, bean, propName);
}
return bean;
}
public Object deserializeFromString(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_stringCreator != null) {
return _stringCreator.construct(jp.getText());
}
if (_delegatingCreator != null) {
return _delegatingCreator.deserialize(jp, ctxt);
}
throw ctxt.instantiationException(getBeanClass(), "no suitable creator method found");
}
public Object deserializeFromNumber(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_numberCreator != null) {
switch (jp.getNumberType()) {
case INT:
return _numberCreator.construct(jp.getIntValue());
case LONG:
return _numberCreator.construct(jp.getLongValue());
}
}
if (_delegatingCreator != null) {
return _delegatingCreator.deserialize(jp, ctxt);
}
throw ctxt.instantiationException(getBeanClass(), "no suitable creator method found");
}
public Object deserializeUsingCreator(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
if (_delegatingCreator != null) {
return _delegatingCreator.deserialize(jp, ctxt);
}
throw ctxt.mappingException(getBeanClass());
}
/**
* Method called to deserialize bean using "property-based creator":
* this means that a non-default constructor or factory method is
* called, and then possibly other setters. The trick is that
* values for creator method need to be buffered, first; and
* due to non-guaranteed ordering possibly some other properties
* as well.
*
* @since 1.2
*/
protected final Object _deserializeUsingPropertyBased(final JsonParser jp, final DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
final Creator.PropertyBased creator = _propertyBasedCreator;
PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt);
// 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases
TokenBuffer unknown = null;
JsonToken t = jp.getCurrentToken();
for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) {
String propName = jp.getCurrentName();
jp.nextToken(); // to point to value
// creator property?
SettableBeanProperty prop = creator.findCreatorProperty(propName);
if (prop != null) {
// Last creator property to set?
Object value = prop.deserialize(jp, ctxt);
if (buffer.assignParameter(prop.getCreatorIndex(), value)) {
jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT
Object bean = creator.build(buffer);
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(jp, ctxt, bean, unknown);
}
if (unknown != null) { // nope, just extra unknown stuff...
bean = handleUnknownProperties(ctxt, bean, unknown);
}
// or just clean?
return deserialize(jp, ctxt, bean);
}
continue;
}
// regular property? needs buffering
prop = _props.get(propName);
if (prop != null) {
buffer.bufferProperty(prop, prop.deserialize(jp, ctxt));
continue;
}
/* As per [JACKSON-313], things marked as ignorable should not be
* passed to any setter
*/
if (_ignorableProps != null && _ignorableProps.contains(propName)) {
jp.skipChildren();
continue;
}
// "any property"?
if (_anySetter != null) {
buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(jp, ctxt));
continue;
}
// Ok then, let's collect the whole field; name and value
if (unknown == null) {
unknown = new TokenBuffer(jp.getCodec());
}
unknown.writeFieldName(propName);
unknown.copyCurrentStructure(jp);
}
// We hit END_OBJECT, so:
Object bean = creator.build(buffer);
if (unknown != null) {
// polymorphic?
if (bean.getClass() != _beanType.getRawClass()) {
return handlePolymorphic(null, ctxt, bean, unknown);
}
// no, just some extra unknown properties
return handleUnknownProperties(ctxt, bean, unknown);
}
return bean;
}
/*
/**********************************************************
/* Overridable helper methods
/**********************************************************
*/
/**
* Method called when a JSON property is encountered that has not matching
* setter, any-setter or field, and thus can not be assigned.
*/
@Override
protected void handleUnknownProperty(JsonParser jp, DeserializationContext ctxt, Object beanOrClass, String propName)
throws IOException, JsonProcessingException
{
/* 22-Aug-2010, tatu: Caller now mostly checks for ignorable properties, so
* following should not be necessary. However, "handleUnknownProperties()" seems
* to still possibly need it so it is left for now.
*/
// If registered as ignorable, skip
if (_ignoreAllUnknown ||
(_ignorableProps != null && _ignorableProps.contains(propName))) {
jp.skipChildren();
return;
}
/* Otherwise use default handling (call handler(s); if not
* handled, throw exception or skip depending on settings)
*/
super.handleUnknownProperty(jp, ctxt, beanOrClass, propName);
}
/**
* Method called to handle set of one or more unknown properties,
* stored in their entirety in given {@link TokenBuffer}
* (as field entries, name and value).
*/
protected Object handleUnknownProperties(DeserializationContext ctxt, Object bean, TokenBuffer unknownTokens)
throws IOException, JsonProcessingException
{
// First: add closing END_OBJECT as marker
unknownTokens.writeEndObject();
// note: buffer does NOT have starting START_OBJECT
JsonParser bufferParser = unknownTokens.asParser();
while (bufferParser.nextToken() != JsonToken.END_OBJECT) {
String propName = bufferParser.getCurrentName();
// Unknown: let's call handler method
bufferParser.nextToken();
handleUnknownProperty(bufferParser, ctxt, bean, propName);
}
return bean;
}
/**
* Method called in cases where we may have polymorphic deserialization
* case: that is, type of Creator-constructed bean is not the type
* of deserializer itself. It should be a sub-class or implementation
* class; either way, we may have more specific deserializer to use
* for handling it.
*
* @param jp (optional) If not null, parser that has more properties to handle
* (in addition to buffered properties); if null, all properties are passed
* in buffer
*/
protected Object handlePolymorphic(JsonParser jp, DeserializationContext ctxt,
Object bean, TokenBuffer unknownTokens)
throws IOException, JsonProcessingException
{
// First things first: maybe there is a more specific deserializer available?
JsonDeserializer subDeser = _findSubclassDeserializer(ctxt, bean, unknownTokens);
if (subDeser != null) {
if (unknownTokens != null) {
// need to add END_OBJECT marker first
unknownTokens.writeEndObject();
JsonParser p2 = unknownTokens.asParser();
p2.nextToken(); // to get to first data field
bean = subDeser.deserialize(p2, ctxt, bean);
}
// Original parser may also have some leftovers
if (jp != null) {
bean = subDeser.deserialize(jp, ctxt, bean);
}
return bean;
}
// nope; need to use this deserializer. Unknowns we've seen so far?
if (unknownTokens != null) {
bean = handleUnknownProperties(ctxt, bean, unknownTokens);
}
// and/or things left to process via main parser?
if (jp != null) {
bean = deserialize(jp, ctxt, bean);
}
return bean;
}
/**
* Helper method called to (try to) locate deserializer for given sub-type of
* type that this deserializer handles.
*/
protected JsonDeserializer _findSubclassDeserializer(DeserializationContext ctxt, Object bean, TokenBuffer unknownTokens)
throws IOException, JsonProcessingException
{
JsonDeserializer subDeser;
// First: maybe we have already created sub-type deserializer?
synchronized (this) {
subDeser = (_subDeserializers == null) ? null : _subDeserializers.get(new ClassKey(bean.getClass()));
}
if (subDeser != null) {
return subDeser;
}
// If not, maybe we can locate one. First, need provider
DeserializerProvider deserProv = ctxt.getDeserializerProvider();
if (deserProv != null) {
JavaType type = TypeFactory.type(bean.getClass());
subDeser = deserProv.findValueDeserializer(ctxt.getConfig(), type, null, "*this*");
// Also, need to cache it
if (subDeser != null) {
synchronized (this) {
if (_subDeserializers == null) {
_subDeserializers = new HashMap>();;
}
_subDeserializers.put(new ClassKey(bean.getClass()), subDeser);
}
}
}
return subDeser;
}
/*
/**********************************************************
/* Helper methods for error reporting
/**********************************************************
*/
/**
* Method that will modify caught exception (passed in as argument)
* as necessary to include reference information, and to ensure it
* is a subtype of {@link IOException}, or an unchecked exception.
*
* Rules for wrapping and unwrapping are bit complicated; essentially:
*
* Errors are to be passed as is (if uncovered via unwrapping)
* "Plain" IOExceptions (ones that are not of type
* {@link JsonMappingException} are to be passed as is
*
*/
public void wrapAndThrow(Throwable t, Object bean, String fieldName)
throws IOException
{
/* 05-Mar-2009, tatu: But one nasty edge is when we get
* StackOverflow: usually due to infinite loop. But that
* usually gets hidden within an InvocationTargetException...
*/
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors and "plain" IOExceptions to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
// Ditto for IOExceptions... except for mapping exceptions!
if (t instanceof IOException && !(t instanceof JsonMappingException)) {
throw (IOException) t;
}
// [JACKSON-55] Need to add reference information
throw JsonMappingException.wrapWithPath(t, bean, fieldName);
}
public void wrapAndThrow(Throwable t, Object bean, int index)
throws IOException
{
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors and "plain" IOExceptions to be passed as is
if (t instanceof Error) {
throw (Error) t;
}
// Ditto for IOExceptions... except for mapping exceptions!
if (t instanceof IOException && !(t instanceof JsonMappingException)) {
throw (IOException) t;
}
// [JACKSON-55] Need to add reference information
throw JsonMappingException.wrapWithPath(t, bean, index);
}
}