Fix #2324
diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x
index 7af3dee..b5a8951 100644
--- a/release-notes/CREDITS-2.x
+++ b/release-notes/CREDITS-2.x
@@ -842,3 +842,7 @@
* Reported #2303: Deserialize null, when java type is "TypeRef of TypeRef of T",
does not provide "Type(Type(null))"
(2.9.9)
+
+Daniil Barvitsky (dbarvitsky@github(
+ * Reported #2324: `StringCollectionDeserializer` fails with custom collection
+ (2.9.9)
diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x
index 720082a..024d8f2 100644
--- a/release-notes/VERSION-2.x
+++ b/release-notes/VERSION-2.x
@@ -18,6 +18,8 @@
(contributed by Christoph F)
#2303: Deserialize null, when java type is "TypeRef of TypeRef of T", does not provide "Type(Type(null))"
(reported by Cyril M)
+#2324: `StringCollectionDeserializer` fails with custom collection
+ (reported byb Daniil B)
- Prevent String coercion of `null` in `WritableObjectId` when calling `JsonGenerator.writeObjectId()`,
mostly relevant for formats like YAML that have native Object Ids
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java
index 321df6f..0bf2e12 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java
@@ -103,8 +103,12 @@
// May need to resolve types for delegate-based creators:
JsonDeserializer<Object> delegate = null;
if (_valueInstantiator != null) {
- AnnotatedWithParams delegateCreator = _valueInstantiator.getDelegateCreator();
+ // [databind#2324]: check both array-delegating and delegating
+ AnnotatedWithParams delegateCreator = _valueInstantiator.getArrayDelegateCreator();
if (delegateCreator != null) {
+ JavaType delegateType = _valueInstantiator.getArrayDelegateType(ctxt.getConfig());
+ delegate = findDeserializer(ctxt, delegateType, property);
+ } else if ((delegateCreator = _valueInstantiator.getDelegateCreator()) != null) {
JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig());
delegate = findDeserializer(ctxt, delegateType, property);
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreator2324Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreator2324Test.java
new file mode 100644
index 0000000..18882cb
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreator2324Test.java
@@ -0,0 +1,70 @@
+package com.fasterxml.jackson.databind.deser.creators;
+
+import java.util.AbstractCollection;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+// for [databind#2324]
+public class DelegatingArrayCreator2324Test extends BaseMapTest
+{
+ @JsonDeserialize(as=ImmutableBag.class)
+ public interface Bag<T> extends Collection<T> { }
+
+ public static class ImmutableBag<T> extends AbstractCollection<T> implements Bag<T> {
+ @Override
+ public Iterator<T> iterator() { return elements.iterator(); }
+
+ @Override
+ public int size() { return elements.size(); }
+
+ @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
+ private ImmutableBag(Collection<T> elements ) {
+ this.elements = Collections.unmodifiableCollection(elements);
+ }
+
+ private final Collection<T> elements;
+ }
+
+ static class Value {
+ public String value;
+
+ public Value(String v) { value = v; }
+
+ @Override
+ public boolean equals(Object o) {
+ return value.equals(((Value) o).value);
+ }
+ }
+
+ static class WithBagOfStrings {
+ public Bag<String> getStrings() { return this.bagOfStrings; }
+ public void setStrings(Bag<String> bagOfStrings) { this.bagOfStrings = bagOfStrings; }
+ private Bag<String> bagOfStrings;
+ }
+
+ static class WithBagOfValues {
+ public Bag<Value> getValues() { return this.bagOfValues; }
+ public void setValues(Bag<Value> bagOfValues) { this.bagOfValues = bagOfValues; }
+ private Bag<Value> bagOfValues;
+ }
+
+ private final ObjectMapper MAPPER = objectMapper();
+
+ public void testDeserializeBagOfStrings() throws Exception {
+ WithBagOfStrings result = MAPPER.readerFor(WithBagOfStrings.class)
+ .readValue("{\"strings\": [ \"a\", \"b\", \"c\"]}");
+ assertEquals(3, result.getStrings().size());
+ }
+
+ public void testDeserializeBagOfPOJOs() throws Exception {
+ WithBagOfValues result = MAPPER.readerFor(WithBagOfValues.class)
+ .readValue("{\"values\": [ \"a\", \"b\", \"c\"]}");
+ assertEquals(3, result.getValues().size());
+ assertEquals(new Value("a"), result.getValues().iterator().next());
+ }
+}