Skip to content

Commit

Permalink
Merge pull request #384 from yinzara/master
Browse files Browse the repository at this point in the history
Added new UNWRAP_SINGLE_VALUE_ARRAYS DeserializationFeature
  • Loading branch information
cowtowncoder committed Jan 10, 2014
2 parents ad9a43f + f190cb5 commit d499f2e
Show file tree
Hide file tree
Showing 15 changed files with 947 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <p>
* Feature is disabled by default
*/
UNWRAP_SINGLE_VALUE_ARRAYS(false),

/**
* Feature to allow "unwrapping" root-level JSON value, to match setting of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
}
Loading

0 comments on commit d499f2e

Please sign in to comment.