Skip to content

Commit

Permalink
Fix #2608
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Apr 5, 2020
1 parent 87804ad commit 4e253a3
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 41 deletions.
3 changes: 3 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ Project: jackson-databind
(reported by Bartosz B)
#2592: `ObjectMapper.setSerializationInclusion()` is ignored for `JsonAnyGetter`
(reported by Oleksii K)
#2608: `ValueInstantiationException` when deserializing using a builder and
`UNWRAP_SINGLE_VALUE_ARRAYS`
(reported by cadrake@github)
#2627: JsonIgnoreProperties(ignoreUnknown = true) does not work on field and method level
(reported by robotmrv@github)
#2632: Failure to resolve generic type parameters on serialization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ protected final Object _deserializeOther(JsonParser p, DeserializationContext ct
case VALUE_NULL:
return deserializeFromNull(p, ctxt);
case START_ARRAY:
// these only work if there's a (delegating) creator...
return deserializeFromArray(p, ctxt);
// these only work if there's a (delegating) creator, or UNWRAP_SINGLE_ARRAY
return _deserializeFromArray(p, ctxt);
case FIELD_NAME:
case END_OBJECT: // added to resolve [JACKSON-319], possible related issues
if (_vanillaProcessing) {
Expand Down Expand Up @@ -567,6 +567,41 @@ protected Object deserializeFromNull(JsonParser p, DeserializationContext ctxt)
return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
}

@Override
protected Object _deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException
{
// note: cannot call `_delegateDeserializer()` since order reversed here:
JsonDeserializer<Object> delegateDeser = _arrayDelegateDeserializer;
// fallback to non-array delegate
if ((delegateDeser != null) || ((delegateDeser = _delegateDeserializer) != null)) {
Object bean = _valueInstantiator.createUsingArrayDelegate(ctxt,
delegateDeser.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
return null;
}
final Object value = deserialize(p, ctxt);
if (p.nextToken() != JsonToken.END_ARRAY) {
handleMissingEndArrayForSingle(p, ctxt);
}
return value;
}
if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY) {
return null;
}
return ctxt.handleUnexpectedToken(getValueType(ctxt), JsonToken.START_ARRAY, p, null);
}
return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
}

/*
/**********************************************************
/* Deserializing when we have to consider an active View
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1445,38 +1445,15 @@ public Object deserializeFromBoolean(JsonParser p, DeserializationContext ctxt)
return _valueInstantiator.createFromBoolean(ctxt, value);
}

public Object deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException
{
// note: cannot call `_delegateDeserializer()` since order reversed here:
JsonDeserializer<Object> delegateDeser = _arrayDelegateDeserializer;
// fallback to non-array delegate
if ((delegateDeser != null) || ((delegateDeser = _delegateDeserializer) != null)) {
Object bean = _valueInstantiator.createUsingArrayDelegate(ctxt,
delegateDeser.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, bean);
}
return bean;
}
if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
return null;
}
final Object value = deserialize(p, ctxt);
if (p.nextToken() != JsonToken.END_ARRAY) {
handleMissingEndArrayForSingle(p, ctxt);
}
return value;
}
if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY) {
return null;
}
return ctxt.handleUnexpectedToken(getValueType(ctxt), JsonToken.START_ARRAY, p, null);
}
return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
/**
* @deprecated Since 2.11 Should not be used: was never meant to be called by
* code other than sub-classes (implementations), and implementations details
* differ
*/
@Deprecated
public Object deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException {
// should work as subtypes ought to override this method:
return _deserializeFromArray(p, ctxt);
}

public Object deserializeFromEmbedded(JsonParser p, DeserializationContext ctxt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,7 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt)
if (_vanillaProcessing) {
return finishBuild(ctxt, vanillaDeserialize(p, ctxt, t));
}
Object builder = deserializeFromObject(p, ctxt);
return finishBuild(ctxt, builder);
return finishBuild(ctxt, deserializeFromObject(p, ctxt));
}
// and then others, generally requiring use of @JsonCreator
switch (p.getCurrentTokenId()) {
Expand All @@ -214,8 +213,9 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt)
case JsonTokenId.ID_FALSE:
return finishBuild(ctxt, deserializeFromBoolean(p, ctxt));
case JsonTokenId.ID_START_ARRAY:
// these only work if there's a (delegating) creator...
return finishBuild(ctxt, deserializeFromArray(p, ctxt));
// these only work if there's a (delegating) creator, or UNWRAP_SINGLE_ARRAY
// [databind#2608]: Do NOT call `finishBuild()` as method implements it
return _deserializeFromArray(p, ctxt);
case JsonTokenId.ID_FIELD_NAME:
case JsonTokenId.ID_END_OBJECT:
return finishBuild(ctxt, deserializeFromObject(p, ctxt));
Expand Down Expand Up @@ -478,6 +478,41 @@ protected final Object _deserialize(JsonParser p,
return builder;
}

@Override // since 2.11, custom implementation
protected Object _deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException
{
// note: cannot call `_delegateDeserializer()` since order reversed here:
JsonDeserializer<Object> delegateDeser = _arrayDelegateDeserializer;
// fallback to non-array delegate
if ((delegateDeser != null) || ((delegateDeser = _delegateDeserializer) != null)) {
Object builder = _valueInstantiator.createUsingArrayDelegate(ctxt,
delegateDeser.deserialize(p, ctxt));
if (_injectables != null) {
injectValues(ctxt, builder);
}
return finishBuild(ctxt, builder);
}
if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY && ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
return null;
}
final Object value = deserialize(p, ctxt);
if (p.nextToken() != JsonToken.END_ARRAY) {
handleMissingEndArrayForSingle(p, ctxt);
}
return value;
}
if (ctxt.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)) {
JsonToken t = p.nextToken();
if (t == JsonToken.END_ARRAY) {
return null;
}
return ctxt.handleUnexpectedToken(getValueType(ctxt), JsonToken.START_ARRAY, p, null);
}
return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
}

/*
/**********************************************************
/* Deserializing when we have to consider an active View
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.fasterxml.jackson.failing;
package com.fasterxml.jackson.databind.deser.builder;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
Expand Down Expand Up @@ -70,8 +70,8 @@ public void testDeserializationAndFail() throws Exception {
.build();

// Regular POJO would work:
// final String serialized = "{\"id\": 1, \"value\": {\"subValue\": \"123\"}}";
final String serialized = "{\"id\": 1, \"value\": [ {\"subValue\": \"123\"} ]}";
// final String serialized = "{\"value\": {\"subValue\": \"123\"}}";
final String serialized = "{\"value\": [ {\"subValue\": \"123\"} ]}";
final ExamplePOJO2608 result = mapper.readValue(serialized, ExamplePOJO2608.class);
assertNotNull(result);
}
Expand Down

0 comments on commit 4e253a3

Please sign in to comment.