diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java index 4dc97e3f36..8ced4b67bf 100644 --- a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java +++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java @@ -203,6 +203,15 @@ public enum DeserializationFeature implements ConfigFeature * Feature is disabled by default. */ ACCEPT_SINGLE_VALUE_AS_ARRAY(false), + + /** + * Feature that determines whether it is acceptable to coerce single value array (in JSON) + * values to the corresponding value type. This is basically the opposite of the {@link #ACCEPT_SINGLE_VALUE_AS_ARRAY} + * feature. If more than one value is found in the array, a JsonMappingException is thrown. + *
+ * Feature is disabled by default
+ */
+ UNWRAP_SINGLE_VALUE_ARRAYS(false),
/**
* Feature to allow "unwrapping" root-level JSON value, to match setting of
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
index c1e2d74675..c0f7c54b49 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
@@ -1211,6 +1211,14 @@ public Object deserializeFromArray(JsonParser jp, DeserializationContext ctxt)
} catch (Exception e) {
wrapInstantiationProblem(e, ctxt);
}
+ } else if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Object value = deserialize(jp, ctxt);
+ if (jp.nextToken() != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array");
+ }
+ return value;
}
throw ctxt.mappingException(getBeanClass());
}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java
index a1e4b46fd5..b5d182f14d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java
@@ -13,6 +13,7 @@
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
@@ -143,19 +144,33 @@ public JsonDeserializer> createContextual(DeserializationContext ctxt, BeanPro
protected java.util.Date _parseDate(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
- if (_customFormat != null && jp.getCurrentToken() == JsonToken.VALUE_STRING) {
- String str = jp.getText().trim();
- if (str.length() == 0) {
- return (Date) getEmptyValue();
- }
- synchronized (_customFormat) {
- try {
- return _customFormat.parse(str);
- } catch (ParseException e) {
- throw new IllegalArgumentException("Failed to parse Date value '"+str
- +"' (format: \""+_formatString+"\"): "+e.getMessage());
+ if (_customFormat != null) {
+ JsonToken t = jp.getCurrentToken();
+ if (t == JsonToken.VALUE_STRING) {
+ String str = jp.getText().trim();
+ if (str.length() == 0) {
+ return (Date) getEmptyValue();
+ }
+ synchronized (_customFormat) {
+ try {
+ return _customFormat.parse(str);
+ } catch (ParseException e) {
+ throw new IllegalArgumentException("Failed to parse Date value '"+str
+ +"' (format: \""+_formatString+"\"): "+e.getMessage());
+ }
}
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Date parsed = _parseDate(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'java.util.Date' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
}
return super._parseDate(jp, ctxt);
}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
index dab3d00b05..1fddc4d11a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
@@ -111,6 +111,19 @@ public Enum> deserialize(JsonParser jp, DeserializationContext ctxt)
}
return result;
}
+
+ // Issue#381
+ if (curr == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Enum> parsed = deserialize(jp, ctxt);
+ curr = jp.nextToken();
+ if (curr != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single '" + _resolver.getEnumClass().getName() + "' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
+
throw ctxt.mappingException(_resolver.getEnumClass());
}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java
index 2d4aa3f17a..dab1d39074 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java
@@ -13,6 +13,7 @@
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.fasterxml.jackson.databind.util.ClassUtil;
@@ -98,6 +99,16 @@ public static Std findDeserializer(Class> rawType)
@Override
public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
{
+ // Issue#381
+ if (jp.getCurrentToken() == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final T value = deserialize(jp, ctxt);
+ if (jp.nextToken() != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array");
+ }
+ return value;
+ }
// 22-Sep-2012, tatu: For 2.1, use this new method, may force coercion:
String text = jp.getValueAsString();
if (text != null) { // has String representation
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java
index 27501e449c..606d847bc5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/NumberDeserializers.java
@@ -238,10 +238,9 @@ public Character deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
- int value;
-
+
if (t == JsonToken.VALUE_NUMBER_INT) { // ok iff ascii value
- value = jp.getIntValue();
+ int value = jp.getIntValue();
if (value >= 0 && value <= 0xFFFF) {
return Character.valueOf((char) value);
}
@@ -254,7 +253,21 @@ public Character deserialize(JsonParser jp, DeserializationContext ctxt)
// actually, empty should become null?
if (text.length() == 0) {
return (Character) getEmptyValue();
+ }
+ } else if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ //Issue#381
+ jp.nextToken();
+ final Character value = deserialize(jp, ctxt);
+ if (jp.nextToken() != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array"
+ );
}
+ return value;
+ } else if (t == JsonToken.VALUE_NULL && !_valueClass.isPrimitive()) {
+ //Issue#unreported
+ // This handles the case where the value required is the Character wrapper class and the token is the null token
+ return getEmptyValue();
}
throw ctxt.mappingException(_valueClass, t);
}
@@ -436,6 +449,17 @@ public Number deserialize(JsonParser jp, DeserializationContext ctxt)
throw ctxt.weirdStringException(text, _valueClass, "not a valid number");
}
}
+
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Number value = deserialize(jp, ctxt);
+ if (jp.nextToken() != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single '" + _valueClass.getName() + "' value but there was more than a single value in the array"
+ );
+ }
+ return value;
+ }
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
@@ -502,10 +526,19 @@ public BigInteger deserialize(JsonParser jp, DeserializationContext ctxt)
* Could do by calling BigDecimal.toBigIntegerExact()
*/
return jp.getDecimalValue().toBigInteger();
+ } else if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final BigInteger value = deserialize(jp, ctxt);
+ if (jp.nextToken() != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'BigInteger' value but there was more than a single value in the array"
+ );
+ }
+ return value;
} else if (t != JsonToken.VALUE_STRING) { // let's do implicit re-parse
// String is ok too, can easily convert; otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
- }
+ }
text = jp.getText().trim();
if (text.length() == 0) {
return null;
@@ -547,6 +580,17 @@ public BigDecimal deserialize(JsonParser jp, DeserializationContext ctxt)
throw ctxt.weirdStringException(text, _valueClass, "not a valid representation");
}
}
+
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final BigDecimal value = deserialize(jp, ctxt);
+ if (jp.nextToken() != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'BigDecimal' value but there was more than a single value in the array"
+ );
+ }
+ return value;
+ }
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java
index 2be93943d6..6dc16a3880 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java
@@ -6,6 +6,7 @@
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
public class StackTraceElementDeserializer
@@ -45,7 +46,17 @@ public StackTraceElement deserialize(JsonParser jp, DeserializationContext ctxt)
}
}
return new StackTraceElement(className, methodName, fileName, lineNumber);
+ } else if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final StackTraceElement value = deserialize(jp, ctxt);
+ if (jp.nextToken() != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'java.lang.StackTraceElement' value but there was more than a single value in the array"
+ );
+ }
+ return value;
}
+
throw ctxt.mappingException(_valueClass, t);
}
}
\ No newline at end of file
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
index cf236b9273..4f1229a44b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
@@ -134,6 +134,17 @@ protected final boolean _parseBooleanPrimitive(JsonParser jp, DeserializationCon
}
throw ctxt.weirdStringException(text, _valueClass, "only \"true\" or \"false\" recognized");
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final boolean parsed = _parseBooleanPrimitive(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'boolean' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
@@ -176,6 +187,17 @@ protected final Boolean _parseBoolean(JsonParser jp, DeserializationContext ctxt
}
throw ctxt.weirdStringException(text, _valueClass, "only \"true\" or \"false\" recognized");
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Boolean parsed = _parseBoolean(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'Boolean' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
@@ -226,6 +248,17 @@ protected Byte _parseByte(JsonParser jp, DeserializationContext ctxt)
if (t == JsonToken.VALUE_NULL) {
return (Byte) getNullValue();
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Byte parsed = _parseByte(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'Byte' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
throw ctxt.mappingException(_valueClass, t);
}
@@ -260,6 +293,17 @@ protected Short _parseShort(JsonParser jp, DeserializationContext ctxt)
if (t == JsonToken.VALUE_NULL) {
return (Short) getNullValue();
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Short parsed = _parseShort(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'Short' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
throw ctxt.mappingException(_valueClass, t);
}
@@ -310,6 +354,17 @@ protected final int _parseIntPrimitive(JsonParser jp, DeserializationContext ctx
if (t == JsonToken.VALUE_NULL) {
return 0;
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final int parsed = _parseIntPrimitive(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'int' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
@@ -347,6 +402,17 @@ protected final Integer _parseInteger(JsonParser jp, DeserializationContext ctxt
if (t == JsonToken.VALUE_NULL) {
return (Integer) getNullValue();
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Integer parsed = _parseInteger(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'Integer' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
@@ -377,6 +443,17 @@ protected final Long _parseLong(JsonParser jp, DeserializationContext ctxt) thro
if (t == JsonToken.VALUE_NULL) {
return (Long) getNullValue();
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Long parsed = _parseLong(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'Long' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
@@ -401,6 +478,17 @@ protected final long _parseLongPrimitive(JsonParser jp, DeserializationContext c
if (t == JsonToken.VALUE_NULL) {
return 0L;
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final long parsed = _parseLongPrimitive(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'long' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
throw ctxt.mappingException(_valueClass, t);
}
@@ -447,6 +535,17 @@ protected final Float _parseFloat(JsonParser jp, DeserializationContext ctxt)
if (t == JsonToken.VALUE_NULL) {
return (Float) getNullValue();
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Float parsed = _parseFloat(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'Byte' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
@@ -489,6 +588,17 @@ protected final float _parseFloatPrimitive(JsonParser jp, DeserializationContext
if (t == JsonToken.VALUE_NULL) {
return 0.0f;
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final float parsed = _parseFloatPrimitive(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'float' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
}
@@ -533,6 +643,17 @@ protected final Double _parseDouble(JsonParser jp, DeserializationContext ctxt)
}
if (t == JsonToken.VALUE_NULL) {
return (Double) getNullValue();
+ }
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Double parsed = _parseDouble(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'Double' value but there was more than a single value in the array");
+ }
+ return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
@@ -577,6 +698,17 @@ protected final double _parseDoublePrimitive(JsonParser jp, DeserializationConte
}
if (t == JsonToken.VALUE_NULL) {
return 0.0;
+ }
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final double parsed = _parseDoublePrimitive(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'Byte' value but there was more than a single value in the array");
+ }
+ return parsed;
}
// Otherwise, no can do:
throw ctxt.mappingException(_valueClass, t);
@@ -609,6 +741,17 @@ protected java.util.Date _parseDate(JsonParser jp, DeserializationContext ctxt)
"not a valid representation (error: "+iae.getMessage()+")");
}
}
+ // Issue#381
+ if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final Date parsed = _parseDate(jp, ctxt);
+ t = jp.nextToken();
+ if (t != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'java.util.Date' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
throw ctxt.mappingException(_valueClass, t);
}
@@ -635,6 +778,16 @@ protected final static double parseDouble(String numStr) throws NumberFormatExce
protected final String _parseString(JsonParser jp, DeserializationContext ctxt)
throws IOException
{
+ // Issue#381
+ if (jp.getCurrentToken() == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
+ jp.nextToken();
+ final String parsed = _parseString(jp, ctxt);
+ if (jp.nextToken() != JsonToken.END_ARRAY) {
+ throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY,
+ "Attempted to unwrap single value array for single 'String' value but there was more than a single value in the array");
+ }
+ return parsed;
+ }
String value = jp.getValueAsString();
if (value != null) {
return value;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java
index dcb01ded45..81b104650a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java
@@ -5,6 +5,7 @@
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
@@ -23,6 +24,16 @@ public final class StringDeserializer extends StdScalarDeserializer