diff options
author | Tatu Saloranta <tatu.saloranta@iki.fi> | 2016-10-05 23:21:57 -0700 |
---|---|---|
committer | Tatu Saloranta <tatu.saloranta@iki.fi> | 2016-10-05 23:21:57 -0700 |
commit | d068a401140fb876757f37d694dfa271933752ac (patch) | |
tree | 08553eff537f3b0ebc5d1584d3dc213674753e56 /src/main/java | |
parent | 816bbed534c8541b2257d58688a0e43792047291 (diff) | |
download | jackson-databind-d068a401140fb876757f37d694dfa271933752ac.tar.gz |
Fix #1035
Diffstat (limited to 'src/main/java')
5 files changed, 84 insertions, 28 deletions
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java index 7942eff5c..7bd6e3e70 100644 --- a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java +++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java @@ -3,11 +3,7 @@ package com.fasterxml.jackson.databind; import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; +import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.annotation.JsonFormat; diff --git a/src/main/java/com/fasterxml/jackson/databind/KeyDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/KeyDeserializer.java index 90dd56da6..217527d41 100644 --- a/src/main/java/com/fasterxml/jackson/databind/KeyDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/KeyDeserializer.java @@ -2,8 +2,6 @@ package com.fasterxml.jackson.databind; import java.io.IOException; -import com.fasterxml.jackson.core.*; - /** * Abstract class that defines API used for deserializing JSON content * field names into Java Map keys. These deserializers are only used @@ -15,7 +13,7 @@ public abstract class KeyDeserializer * Method called to deserialize a {@link java.util.Map} key from JSON property name. */ public abstract Object deserializeKey(String key, DeserializationContext ctxt) - throws IOException, JsonProcessingException; + throws IOException; /** * This marker class is only to be used with annotations, to diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java index d80c23d03..750c3c26b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java @@ -1781,6 +1781,23 @@ public abstract class BasicDeserializerFactory } /** + * @since 2.9 + */ + protected JsonDeserializer<Object> findContentDeserializerFromAnnotation(DeserializationContext ctxt, + Annotated ann) + throws JsonMappingException + { + AnnotationIntrospector intr = ctxt.getAnnotationIntrospector(); + if (intr != null) { + Object deserDef = intr.findContentDeserializer(ann); + if (deserDef != null) { + return ctxt.deserializerInstance(ann, deserDef); + } + } + return null; + } + + /** * Helper method used to resolve additional type-related annotation information * like type overrides, or handler (serializer, deserializer) overrides, * so that from declared field, property or constructor parameter type diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java index 06217d2a6..ad37f3ad7 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java @@ -679,31 +679,59 @@ public class BeanDeserializerFactory throws JsonMappingException { //find the java type based on the annotated setter method or setter field - JavaType type = null; + BeanProperty prop; + JavaType keyType; + JavaType valueType; + if (mutator instanceof AnnotatedMethod) { // we know it's a 2-arg method, second arg is the value - type = ((AnnotatedMethod) mutator).getParameterType(1); + AnnotatedMethod am = (AnnotatedMethod) mutator; + keyType = am.getParameterType(0); + valueType = am.getParameterType(1); + valueType = resolveMemberAndTypeAnnotations(ctxt, mutator, valueType); + prop = new BeanProperty.Std(PropertyName.construct(mutator.getName()), + valueType, null, beanDesc.getClassAnnotations(), mutator, + PropertyMetadata.STD_OPTIONAL); + } else if (mutator instanceof AnnotatedField) { + AnnotatedField af = (AnnotatedField) mutator; // get the type from the content type of the map object - type = ((AnnotatedField) mutator).getType().getContentType(); - } - // First: various annotations on type itself, as well as type-overrides - // on accessor need to be resolved - type = resolveMemberAndTypeAnnotations(ctxt, mutator, type); - BeanProperty.Std prop = new BeanProperty.Std(PropertyName.construct(mutator.getName()), - type, null, beanDesc.getClassAnnotations(), mutator, - PropertyMetadata.STD_OPTIONAL); + JavaType mapType = af.getType(); + mapType = resolveMemberAndTypeAnnotations(ctxt, mutator, mapType); + keyType = mapType.getKeyType(); + valueType = mapType.getContentType(); + prop = new BeanProperty.Std(PropertyName.construct(mutator.getName()), + mapType, null, beanDesc.getClassAnnotations(), mutator, + PropertyMetadata.STD_OPTIONAL); + } else { + return ctxt.reportBadDefinition(beanDesc.getType(), String.format( + "Unrecognized mutator type for any setter: %s", mutator.getClass())); + } + // First: see if there are explicitly specified // and then possible direct deserializer override on accessor - JsonDeserializer<Object> deser = findDeserializerFromAnnotation(ctxt, mutator); + KeyDeserializer keyDeser = findKeyDeserializerFromAnnotation(ctxt, mutator); + if (keyDeser == null) { + keyDeser = keyType.getValueHandler(); + } + if (keyDeser == null) { + keyDeser = ctxt.findKeyDeserializer(keyType, prop); + } else { + if (keyDeser instanceof ContextualKeyDeserializer) { + keyDeser = ((ContextualKeyDeserializer) keyDeser) + .createContextual(ctxt, prop); + } + } + JsonDeserializer<Object> deser = findContentDeserializerFromAnnotation(ctxt, mutator); if (deser == null) { - deser = type.getValueHandler(); + deser = valueType.getValueHandler(); } if (deser != null) { // As per [databind#462] need to ensure we contextualize deserializer before passing it on - deser = (JsonDeserializer<Object>) ctxt.handlePrimaryContextualization(deser, prop, type); + deser = (JsonDeserializer<Object>) ctxt.handlePrimaryContextualization(deser, prop, valueType); } - TypeDeserializer typeDeser = type.getTypeHandler(); - return new SettableAnyProperty(prop, mutator, type, deser, typeDeser); + TypeDeserializer typeDeser = valueType.getTypeHandler(); + return new SettableAnyProperty(prop, mutator, valueType, + keyDeser, deser, typeDeser); } /** diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java index 8ee86d433..ead2f39b4 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java @@ -42,7 +42,12 @@ public class SettableAnyProperty protected JsonDeserializer<Object> _valueDeserializer; protected final TypeDeserializer _valueTypeDeserializer; - + + /** + * @since 2.9 + */ + protected final KeyDeserializer _keyDeserializer; + /* /********************************************************** /* Life-cycle @@ -50,6 +55,7 @@ public class SettableAnyProperty */ public SettableAnyProperty(BeanProperty property, AnnotatedMember setter, JavaType type, + KeyDeserializer keyDeser, JsonDeserializer<Object> valueDeser, TypeDeserializer typeDeser) { _property = property; @@ -57,9 +63,17 @@ public class SettableAnyProperty _type = type; _valueDeserializer = valueDeser; _valueTypeDeserializer = typeDeser; + _keyDeserializer = keyDeser; _setterIsField = setter instanceof AnnotatedField; } + @Deprecated // since 2.9 + public SettableAnyProperty(BeanProperty property, AnnotatedMember setter, JavaType type, + JsonDeserializer<Object> valueDeser, TypeDeserializer typeDeser) + { + this(property, setter, type, null, valueDeser, typeDeser); + } + /** * Constructor used for JDK Serialization when reading persisted object */ @@ -70,12 +84,13 @@ public class SettableAnyProperty _type = src._type; _valueDeserializer = src._valueDeserializer; _valueTypeDeserializer = src._valueTypeDeserializer; + _keyDeserializer = src._keyDeserializer; _setterIsField = src._setterIsField; } public SettableAnyProperty withValueDeserializer(JsonDeserializer<Object> deser) { return new SettableAnyProperty(_property, _setter, _type, - deser, _valueTypeDeserializer); + _keyDeserializer, deser, _valueTypeDeserializer); } public void fixAccess(DeserializationConfig config) { @@ -127,7 +142,9 @@ public class SettableAnyProperty throws IOException { try { - set(instance, propName, deserialize(p, ctxt)); + Object key = (_keyDeserializer == null) ? propName + : _keyDeserializer.deserializeKey(propName, ctxt); + set(instance, key, deserialize(p, ctxt)); } catch (UnresolvedForwardReference reference) { if (!(_valueDeserializer.getObjectIdReader() != null)) { throw JsonMappingException.from(p, "Unresolved forward reference but no identity info.", reference); @@ -151,7 +168,7 @@ public class SettableAnyProperty } @SuppressWarnings("unchecked") - public void set(Object instance, String propName, Object value) throws IOException + public void set(Object instance, Object propName, Object value) throws IOException { try { // if annotation in the field (only map is supported now) @@ -187,7 +204,7 @@ public class SettableAnyProperty * @param propName Name of property (from Json input) to set * @param value Value of the property */ - protected void _throwAsIOE(Exception e, String propName, Object value) + protected void _throwAsIOE(Exception e, Object propName, Object value) throws IOException { if (e instanceof IllegalArgumentException) { |