Skip to content

Commit bc97be3

Browse files
committed
Refactor CollectionDeserializer (take 2) to solve FasterXML/jackson-dataformats-text#199
1 parent 400f546 commit bc97be3

File tree

3 files changed

+38
-30
lines changed

3 files changed

+38
-30
lines changed

release-notes/VERSION-2.x

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Project: jackson-databind
2020
registered custom (de)serializers
2121
#2707: Improve description included in by `DeserializationContext.handleUnexpectedToken()`
2222
- Add `BeanDeserializerBase.isCaseInsensitive()`
23+
- Some refactoring of `CollectionDeserializer` to solve CSV array handling issues
2324

2425
2.11.1 (not yet released)
2526

src/main/java/com/fasterxml/jackson/databind/deser/std/ArrayBlockingQueueDeserializer.java

+7-9
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,16 @@ protected Collection<Object> createDefaultInstance(DeserializationContext ctxt)
8585
return null;
8686
}
8787

88+
// NOTE: implementation changed between 2.11 and 2.12
8889
@Override
89-
public Collection<Object> deserialize(JsonParser p, DeserializationContext ctxt,
90-
Collection<Object> result0) throws IOException
90+
protected Collection<Object> _deserializeFromArray(JsonParser p, DeserializationContext ctxt,
91+
Collection<Object> result0)
92+
throws IOException
9193
{
92-
if (result0 != null) {
93-
return super.deserialize(p, ctxt, result0);
94-
}
95-
// Ok: must point to START_ARRAY (or equivalent)
96-
if (!p.isExpectedStartArrayToken()) {
97-
return handleNonArray(p, ctxt, new ArrayBlockingQueue<>(1));
94+
if (result0 == null) { // usual case
95+
result0 = new ArrayList<>();
9896
}
99-
result0 = super.deserialize(p, ctxt, new ArrayList<>());
97+
result0 = super._deserializeFromArray(p, ctxt, result0);
10098
if (result0.isEmpty()) {
10199
return new ArrayBlockingQueue<>(1, false);
102100
}

src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java

+30-21
Original file line numberDiff line numberDiff line change
@@ -232,22 +232,21 @@ public Collection<Object> deserialize(JsonParser p, DeserializationContext ctxt)
232232
return (Collection<Object>) _valueInstantiator.createUsingDelegate(ctxt,
233233
_delegateDeserializer.deserialize(p, ctxt));
234234
}
235+
// 16-May-2020, tatu: As per [dataformats-text#199] need to first check for
236+
// possible Array-coercion and only after that String coercion
237+
if (p.isExpectedStartArrayToken()) {
238+
return _deserializeFromArray(p, ctxt, createDefaultInstance(ctxt));
239+
}
235240
// Empty String may be ok; bit tricky to check, however, since
236241
// there is also possibility of "auto-wrapping" of single-element arrays.
237242
// Hence we only accept empty String here.
238243
if (p.hasToken(JsonToken.VALUE_STRING)) {
239-
// 16-May-2020, tatu: As [dataformats-text#199] need to avoid blocking
240-
// check to `isExpectedStartArrayToken()` (needed for CSV in-field array/list logic)
241-
// ... alas, trying to do this here leads to 2 unit test regressions so will
242-
// need to figure out safer mechanism.
243-
// if (_valueInstantiator.canCreateFromString()) {
244-
String str = p.getText();
245-
if (str.length() == 0) {
246-
return (Collection<Object>) _valueInstantiator.createFromString(ctxt, str);
247-
// }
244+
String str = p.getText();
245+
if (str.length() == 0) {
246+
return (Collection<Object>) _valueInstantiator.createFromString(ctxt, str);
248247
}
249248
}
250-
return deserialize(p, ctxt, createDefaultInstance(ctxt));
249+
return handleNonArray(p, ctxt, createDefaultInstance(ctxt));
251250
}
252251

253252
/**
@@ -266,9 +265,28 @@ public Collection<Object> deserialize(JsonParser p, DeserializationContext ctxt,
266265
throws IOException
267266
{
268267
// Ok: must point to START_ARRAY (or equivalent)
269-
if (!p.isExpectedStartArrayToken()) {
270-
return handleNonArray(p, ctxt, result);
268+
if (p.isExpectedStartArrayToken()) {
269+
return _deserializeFromArray(p, ctxt, result);
271270
}
271+
return handleNonArray(p, ctxt, result);
272+
}
273+
274+
@Override
275+
public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
276+
TypeDeserializer typeDeserializer)
277+
throws IOException
278+
{
279+
// In future could check current token... for now this should be enough:
280+
return typeDeserializer.deserializeTypedFromArray(p, ctxt);
281+
}
282+
283+
/**
284+
* @since 2.12
285+
*/
286+
protected Collection<Object> _deserializeFromArray(JsonParser p, DeserializationContext ctxt,
287+
Collection<Object> result)
288+
throws IOException
289+
{
272290
// [databind#631]: Assign current value, to be accessible by custom serializers
273291
p.setCurrentValue(result);
274292

@@ -310,15 +328,6 @@ public Collection<Object> deserialize(JsonParser p, DeserializationContext ctxt,
310328
return result;
311329
}
312330

313-
@Override
314-
public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
315-
TypeDeserializer typeDeserializer)
316-
throws IOException
317-
{
318-
// In future could check current token... for now this should be enough:
319-
return typeDeserializer.deserializeTypedFromArray(p, ctxt);
320-
}
321-
322331
/**
323332
* Helper method called when current token is no START_ARRAY. Will either
324333
* throw an exception, or try to handle value as if member of implicit

0 commit comments

Comments
 (0)