diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java index 063cb22a8e..bf2ae16c7b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java @@ -1,7 +1,11 @@ package com.fasterxml.jackson.databind.deser.std; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; /** @@ -57,4 +61,30 @@ public SettableBeanProperty findBackReference(String refName) { * Accesor for deserializer use for deserializing content values. */ public abstract JsonDeserializer getContentDeserializer(); + + /* + /********************************************************** + /* Shared methods for sub-classes + /********************************************************** + */ + + /** + * Helper method called by various Map(-like) deserializers. + */ + protected void wrapAndThrow(Throwable t, Object ref, String key) throws IOException + { + // to handle StackOverflow: + 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; + } + // ... except for mapping exceptions + if (t instanceof IOException && !(t instanceof JsonMappingException)) { + throw (IOException) t; + } + throw JsonMappingException.wrapWithPath(t, ref, key); + } } diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java index 552af529d6..1a34b6d4d8 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java @@ -4,10 +4,8 @@ import java.util.*; import com.fasterxml.jackson.core.*; - import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.ContextualDeserializer; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; /** @@ -15,12 +13,10 @@ *

* Note: casting within this class is all messed up -- just could not figure out a way * to properly deal with recursive definition of "EnumMap, V> - * - * @author tsaloranta */ @SuppressWarnings({ "unchecked", "rawtypes" }) public class EnumMapDeserializer - extends StdDeserializer> + extends ContainerDeserializerBase> implements ContextualDeserializer { private static final long serialVersionUID = 4564890642370311174L; @@ -47,7 +43,7 @@ public class EnumMapDeserializer public EnumMapDeserializer(JavaType mapType, JsonDeserializer keyDeserializer, JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser) { - super(EnumMap.class); + super(mapType); _mapType = mapType; _enumClass = mapType.getKeyType().getRawClass(); _keyDeserializer = (JsonDeserializer>) keyDeserializer; @@ -96,7 +92,23 @@ public JsonDeserializer createContextual(DeserializationContext ctxt, BeanPro */ @Override public boolean isCachable() { return true; } - + + /* + /********************************************************** + /* ContainerDeserializerBase API + /********************************************************** + */ + + @Override + public JavaType getContentType() { + return _mapType.getContentType(); + } + + @Override + public JsonDeserializer getContentDeserializer() { + return _valueDeserializer; + } + /* /********************************************************** /* Actual deserialization @@ -115,6 +127,8 @@ public EnumMap deserialize(JsonParser jp, DeserializationContext ctxt) thro final TypeDeserializer typeDeser = _valueTypeDeserializer; while ((jp.nextToken()) != JsonToken.END_OBJECT) { + String keyName = jp.getCurrentName(); // just for error message + // but we need to let key deserializer handle it separately, nonetheless Enum key = _keyDeserializer.deserialize(jp, ctxt); if (key == null) { if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { @@ -127,7 +141,7 @@ public EnumMap deserialize(JsonParser jp, DeserializationContext ctxt) thro throw ctxt.weirdStringException(value, _enumClass, "value not one of declared Enum instance names"); } /* 24-Mar-2012, tatu: Null won't work as a key anyway, so let's - * just skip the entry then. But we must skip the value then. + * just skip the entry then. But we must skip the value as well, if so. */ jp.nextToken(); jp.skipChildren(); @@ -139,13 +153,18 @@ public EnumMap deserialize(JsonParser jp, DeserializationContext ctxt) thro * not handle them (and maybe fail or return bogus data) */ Object value; - - if (t == JsonToken.VALUE_NULL) { - value = valueDes.getNullValue(); - } else if (typeDeser == null) { - value = valueDes.deserialize(jp, ctxt); - } else { - value = valueDes.deserializeWithType(jp, ctxt, typeDeser); + + try { + if (t == JsonToken.VALUE_NULL) { + value = valueDes.getNullValue(); + } else if (typeDeser == null) { + value = valueDes.deserialize(jp, ctxt); + } else { + value = valueDes.deserializeWithType(jp, ctxt, typeDeser); + } + } catch (Exception e) { + wrapAndThrow(e, result, keyName); + return null; } result.put(key, value); } diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java index 7c719f03ea..a446777dea 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java @@ -1,7 +1,6 @@ package com.fasterxml.jackson.databind.deser.std; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.util.*; import com.fasterxml.jackson.core.*; @@ -259,7 +258,7 @@ public JsonDeserializer createContextual(DeserializationContext ctxt, } return withResolved(kd, vtd, vd, ignored); } - + /* /********************************************************** /* ContainerDeserializerBase API @@ -538,24 +537,6 @@ public Map _deserializeUsingCreator(JsonParser jp, Deserializatio protected void wrapAndThrow(Throwable t, Object ref) throws IOException { wrapAndThrow(t, ref, null); } - - // note: copied from BeanDeserializer; should try to share somehow... - protected void wrapAndThrow(Throwable t, Object ref, String key) throws IOException - { - // to handle StackOverflow: - 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; - } - // ... except for mapping exceptions - if (t instanceof IOException && !(t instanceof JsonMappingException)) { - throw (IOException) t; - } - throw JsonMappingException.wrapWithPath(t, ref, key); - } private void handleUnresolvedReference(JsonParser jp, MapReferringAccumulator accumulator, Object key, UnresolvedForwardReference reference)