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 e8ca72191e..7fb74da4cf 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
@@ -716,7 +716,7 @@ protected void _addImplicitFactoryCreators(DeserializationContext ctxt,
}
continue;
}
- AnnotatedParameter nonAnnotatedParam = null;
+ AnnotatedParameter nonAnnotatedParam = null;
SettableBeanProperty[] properties = new SettableBeanProperty[argCount];
int implicitNameCount = 0;
int explicitNameCount = 0;
@@ -1474,6 +1474,18 @@ public JsonDeserializer> createCollectionLikeDeserializer(DeserializationConte
return deser;
}
+ @Override
+ public JsonDeserializer> createTupleDeserializer(DeserializationContext ctxt,
+ TupleType type, BeanDescription beanDesc)
+ throws JsonMappingException
+ {
+ CollectionType ct = ctxt.getTypeFactory().constructCollectionType(Collection.class,
+ TypeFactory.unknownType());
+ CollectionDeserializer deser = (CollectionDeserializer) createCollectionDeserializer(ctxt,
+ ct, beanDesc);
+ return new TupleDeserializer(deser, type);
+ }
+
/*
/**********************************************************
/* DeserializerFactory impl: Map(-like) deserializers
@@ -2010,7 +2022,7 @@ public TypeDeserializer findPropertyTypeDeserializer(DeserializationConfig confi
throws JsonMappingException
{
AnnotationIntrospector ai = config.getAnnotationIntrospector();
- TypeResolverBuilder> b = ai.findPropertyTypeResolver(config, annotated, baseType);
+ TypeResolverBuilder> b = ai.findPropertyTypeResolver(config, annotated, baseType);
// Defaulting: if no annotations on member, check value class
if (b == null) {
return findTypeDeserializer(config, baseType);
@@ -2037,13 +2049,13 @@ public TypeDeserializer findPropertyTypeDeserializer(DeserializationConfig confi
*
* @param containerType Type of property; must be a container type
* @param propertyEntity Field or method that contains container property
- */
+ */
public TypeDeserializer findPropertyContentTypeDeserializer(DeserializationConfig config,
JavaType containerType, AnnotatedMember propertyEntity)
throws JsonMappingException
{
AnnotationIntrospector ai = config.getAnnotationIntrospector();
- TypeResolverBuilder> b = ai.findPropertyContentTypeResolver(config, propertyEntity, containerType);
+ TypeResolverBuilder> b = ai.findPropertyContentTypeResolver(config, propertyEntity, containerType);
JavaType contentType = containerType.getContentType();
// Defaulting: if no annotations on member, check class
if (b == null) {
@@ -2086,13 +2098,17 @@ public JsonDeserializer> findDefaultDeserializer(DeserializationContext ctxt,
return StringDeserializer.instance;
}
if (rawType == CLASS_ITERABLE) {
- // [databind#199]: Can and should 'upgrade' to a Collection type:
- TypeFactory tf = ctxt.getTypeFactory();
- JavaType[] tps = tf.findTypeParameters(type, CLASS_ITERABLE);
- JavaType elemType = (tps == null || tps.length != 1) ? TypeFactory.unknownType() : tps[0];
- CollectionType ct = tf.constructCollectionType(Collection.class, elemType);
- // Should we re-introspect beanDesc? For now let's not...
- return createCollectionDeserializer(ctxt, ct, beanDesc);
+ if (type instanceof TupleType) {
+ return createTupleDeserializer(ctxt, (TupleType) type, beanDesc);
+ } else {
+ // [databind#199]: Can and should 'upgrade' to a Collection type:
+ TypeFactory tf = ctxt.getTypeFactory();
+ JavaType[] tps = tf.findTypeParameters(type, CLASS_ITERABLE);
+ // Should we re-introspect beanDesc? For now let's not...
+ JavaType elemType = (tps == null || tps.length != 1) ? TypeFactory.unknownType() : tps[0];
+ CollectionType ct = tf.constructCollectionType(Collection.class, elemType);
+ return createCollectionDeserializer(ctxt, ct, beanDesc);
+ }
}
if (rawType == CLASS_MAP_ENTRY) {
// 28-Apr-2015, tatu: TypeFactory does it all for us already so
@@ -2375,7 +2391,7 @@ protected JavaType resolveMemberAndTypeAnnotations(DeserializationContext ctxt,
type = type.withContentValueHandler(cd);
}
TypeDeserializer contentTypeDeser = findPropertyContentTypeDeserializer(
- ctxt.getConfig(), type, (AnnotatedMember) member);
+ ctxt.getConfig(), type, (AnnotatedMember) member);
if (contentTypeDeser != null) {
type = type.withContentTypeHandler(contentTypeDeser);
}
@@ -2418,7 +2434,7 @@ protected boolean _hasCreatorAnnotation(DeserializationContext ctxt,
AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
if (intr != null) {
JsonCreator.Mode mode = intr.findCreatorAnnotation(ctxt.getConfig(), ann);
- return (mode != null) && (mode != JsonCreator.Mode.DISABLED);
+ return (mode != null) && (mode != JsonCreator.Mode.DISABLED);
}
return false;
}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerFactory.java
index 4451fccffe..6fb8503a67 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerFactory.java
@@ -10,7 +10,7 @@
* {@link JsonDeserializer} instances (which are then cached by
* context and/or dedicated cache).
*
- * Since there are multiple broad categories of deserializers, there are
+ * Since there are multiple broad categories of deserializers, there are
* multiple factory methods:
*
*
For JSON "Array" type, we need 2 methods: one to deal with expected
@@ -165,6 +165,10 @@ public abstract JsonDeserializer> createCollectionLikeDeserializer(Deserializa
CollectionLikeType type, BeanDescription beanDesc)
throws JsonMappingException;
+ public abstract JsonDeserializer> createTupleDeserializer(DeserializationContext ctxt,
+ TupleType type, BeanDescription beanDesc)
+ throws JsonMappingException;
+
public abstract JsonDeserializer> createMapDeserializer(DeserializationContext ctxt,
MapType type, BeanDescription beanDesc)
throws JsonMappingException;
@@ -208,7 +212,7 @@ public abstract TypeDeserializer findTypeDeserializer(DeserializationConfig conf
* given type as opposed to auto-generated "Bean" deserializer. Factory itself will check
* for known JDK-provided types, but registered {@link com.fasterxml.jackson.databind.Module}s
* are also called to see if they might provide explicit deserializer.
- *
+ *
* Main use for this method is with Safe Default Typing (and generally Safe Polymorphic
* Deserialization), during which it is good to be able to check that given raw type
* is explicitly supported and as such "known type" (as opposed to potentially
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/TupleDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/TupleDeserializer.java
new file mode 100644
index 0000000000..ec77664d41
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/TupleDeserializer.java
@@ -0,0 +1,119 @@
+package com.fasterxml.jackson.databind.deser.std;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
+import com.fasterxml.jackson.databind.deser.NullValueProvider;
+import com.fasterxml.jackson.databind.deser.ValueInstantiator;
+import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
+import com.fasterxml.jackson.databind.type.TupleType;
+import com.fasterxml.jackson.databind.util.ClassUtil;
+
+/**
+ * TupleDeserializer
+ */
+@JacksonStdImpl
+public class TupleDeserializer extends CollectionDeserializer {
+ private static final long serialVersionUID = 1L;
+
+ private TupleType tupleType;
+
+ private List> valueDeserList;
+
+ private List nullerList;
+
+ public TupleDeserializer(CollectionDeserializer deser, TupleType tupleType)
+ {
+ // disable unwrapSingle.
+ super(deser._valueType,
+ deser._valueDeserializer, deser._valueTypeDeserializer,
+ deser._valueInstantiator, deser._delegateDeserializer,
+ deser._nullProvider, false);
+ this.tupleType = tupleType;
+ this.valueDeserList = new ArrayList<>();
+ this.nullerList = new ArrayList<>();
+ }
+
+ protected TupleDeserializer (JavaType containerType,
+ JsonDeserializer