下面列出了com.fasterxml.jackson.databind.DeserializationContext#isEnabled ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
protected final JsonDeserializer<Object> _findDefaultImplDeserializer(DeserializationContext ctxt) throws IOException
{
/* 06-Feb-2013, tatu: As per [databind#148], consider default implementation value of
* {@link java.lang.Void} to mean "serialize as null"; as well as DeserializationFeature
* to do swift mapping to null
*/
if (_defaultImpl == null) {
if (!ctxt.isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
return NullifyingDeserializer.instance;
}
return null;
}
Class<?> raw = _defaultImpl.getRawClass();
if (ClassUtil.isBogusClass(raw)) {
return NullifyingDeserializer.instance;
}
synchronized (_defaultImpl) {
if (_defaultImplDeserializer == null) {
_defaultImplDeserializer = ctxt.findContextualValueDeserializer(
_defaultImpl, _property);
}
return _defaultImplDeserializer;
}
}
protected void wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt)
throws IOException
{
// inlined 'throwOrReturnThrowable'
while (t instanceof InvocationTargetException && t.getCause() != null) {
t = t.getCause();
}
// Errors to be passed as is
ClassUtil.throwIfError(t);
// StackOverflowErrors are tricky ones; need to be careful...
boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
// Ditto for IOExceptions; except we may want to wrap JSON exceptions
if (t instanceof IOException) {
if (!wrap || !(t instanceof JsonProcessingException)) {
throw (IOException) t;
}
} else if (!wrap) { // allow disabling wrapping for unchecked exceptions
ClassUtil.throwIfRTE(t);
}
throw JsonMappingException.wrapWithPath(t, bean, fieldName);
}
@Override
public Object deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException
{
switch (p.getCurrentTokenId()) {
case JsonTokenId.ID_START_ARRAY:
case JsonTokenId.ID_START_OBJECT:
case JsonTokenId.ID_FIELD_NAME:
return typeDeserializer.deserializeTypedFromAny(p, ctxt);
case JsonTokenId.ID_STRING:
return p.getText();
case JsonTokenId.ID_NUMBER_INT:
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS)) {
return p.getBigIntegerValue();
}
return p.getNumberValue();
case JsonTokenId.ID_NUMBER_FLOAT:
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
return p.getDecimalValue();
}
return p.getNumberValue();
case JsonTokenId.ID_TRUE:
return Boolean.TRUE;
case JsonTokenId.ID_FALSE:
return Boolean.FALSE;
case JsonTokenId.ID_EMBEDDED_OBJECT:
return p.getEmbeddedObject();
case JsonTokenId.ID_NULL: // should not get this far really but...
return null;
default:
}
return ctxt.handleUnexpectedToken(Object.class, p);
}
/**
* Helper method called when current token is no START_ARRAY. Will either
* throw an exception, or try to handle value as if member of implicit
* array, depending on configuration.
*/
@SuppressWarnings("unchecked")
protected final Collection<Object> handleNonArray(JsonParser p, DeserializationContext ctxt,
Collection<Object> result)
throws IOException {
// Implicit arrays from single values?
boolean canWrap = (_unwrapSingle == Boolean.TRUE) ||
((_unwrapSingle == null) &&
ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
if (!canWrap) {
return (Collection<Object>) ctxt.handleUnexpectedToken(_containerType.getRawClass(), p);
}
JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
JsonToken t = p.getCurrentToken();
Object value;
try {
if (t == JsonToken.VALUE_NULL) {
// 03-Feb-2017, tatu: Hmmh. I wonder... let's try skipping here, too
if (_skipNullValues) {
return result;
}
value = _nullProvider.getNullValue(ctxt);
} else if (typeDeser == null) {
value = valueDes.deserialize(p, ctxt);
} else {
value = valueDes.deserializeWithType(p, ctxt, typeDeser);
}
} catch (Exception e) {
// note: pass Object.class, not Object[].class, as we need element type for error info
throw JsonMappingException.wrapWithPath(e, Object.class, result.size());
}
result.add(value);
return result;
}
@Override
public T deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException {
T result;
try {
result = clazz.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
throw new IOException("Error deserializing JSON!", ex);
}
// need to make subclass of this class for every Entity subclass with custom field to get expected class!!!
BeanDescription beanDescription = ctxt.getConfig().introspect(ctxt.constructType(clazz));
ObjectMapper mapper = (ObjectMapper) parser.getCodec();
JsonNode obj = mapper.readTree(parser);
List<BeanPropertyDefinition> properties = beanDescription.findProperties();
Iterator<Map.Entry<String, JsonNode>> i = obj.fields();
// First check if we know all properties that are present.
if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
while (i.hasNext()) {
Map.Entry<String, JsonNode> next = i.next();
String fieldName = next.getKey();
Optional<BeanPropertyDefinition> findFirst = properties.stream().filter(p -> p.getName().equals(fieldName)).findFirst();
if (!findFirst.isPresent()) {
throw new UnrecognizedPropertyException(parser, "Unknown field: " + fieldName, parser.getCurrentLocation(), clazz, fieldName, null);
}
}
}
for (BeanPropertyDefinition classProperty : properties) {
deserialiseProperty(obj, classProperty, properties, mapper, result);
}
return result;
}
@SuppressWarnings("unchecked")
@Override
public T deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
// Should usually point to START_ARRAY
if (p.isExpectedStartArrayToken()) {
return _deserializeContents(p, ctxt);
}
// But may support implicit arrays from single values?
if (ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) {
return _deserializeFromSingleValue(p, ctxt);
}
return (T) ctxt.handleUnexpectedToken(getValueType(ctxt), p);
}
protected T _fromLong(DeserializationContext context, long timestamp)
{
if(context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)){
return fromNanoseconds.apply(new FromDecimalArguments(
timestamp, 0, this.getZone(context)
));
}
return fromMilliseconds.apply(new FromIntegerArguments(
timestamp, this.getZone(context)));
}
@Override
public Duration deserialize(JsonParser parser, DeserializationContext context) throws IOException
{
switch (parser.currentTokenId())
{
case JsonTokenId.ID_NUMBER_FLOAT:
BigDecimal value = parser.getDecimalValue();
return DecimalUtils.extractSecondsAndNanos(value, Duration::ofSeconds);
case JsonTokenId.ID_NUMBER_INT:
if(context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)) {
return Duration.ofSeconds(parser.getLongValue());
}
return Duration.ofMillis(parser.getLongValue());
case JsonTokenId.ID_STRING:
String string = parser.getText().trim();
if (string.length() == 0) {
if (!isLenient()) {
return _failForNotLenient(parser, context, JsonToken.VALUE_STRING);
}
return null;
}
try {
return Duration.parse(string);
} catch (DateTimeException e) {
return _handleDateTimeException(context, e, string);
}
case JsonTokenId.ID_EMBEDDED_OBJECT:
// 20-Apr-2016, tatu: Related to [databind#1208], can try supporting embedded
// values quite easily
return (Duration) parser.getEmbeddedObject();
case JsonTokenId.ID_START_ARRAY:
return _deserializeFromArray(parser, context);
}
return _handleUnexpectedToken(context, parser, JsonToken.VALUE_STRING,
JsonToken.VALUE_NUMBER_INT, JsonToken.VALUE_NUMBER_FLOAT);
}
@Override
public M deserialize(final JsonParser parser, final DeserializationContext context) throws IOException {
BigDecimal amount = null;
CurrencyUnit currency = null;
while (parser.nextToken() != JsonToken.END_OBJECT) {
final String field = parser.getCurrentName();
parser.nextToken();
if (field.equals(names.getAmount())) {
amount = context.readValue(parser, BigDecimal.class);
} else if (field.equals(names.getCurrency())) {
currency = context.readValue(parser, CurrencyUnit.class);
} else if (field.equals(names.getFormatted())) {
//noinspection UnnecessaryContinue
continue;
} else if (context.isEnabled(FAIL_ON_UNKNOWN_PROPERTIES)) {
throw UnrecognizedPropertyException.from(parser, MonetaryAmount.class, field,
Arrays.asList(names.getAmount(), names.getCurrency(), names.getFormatted()));
} else {
parser.skipChildren();
}
}
checkPresent(parser, amount, names.getAmount());
checkPresent(parser, currency, names.getCurrency());
return factory.create(amount, currency);
}
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
switch (p.getCurrentTokenId()) {
case JsonTokenId.ID_START_OBJECT:
case JsonTokenId.ID_FIELD_NAME:
// 28-Oct-2015, tatu: [databind#989] We may also be given END_OBJECT (similar to FIELD_NAME),
// if caller has advanced to the first token of Object, but for empty Object
case JsonTokenId.ID_END_OBJECT:
if (_mapDeserializer != null) {
return _mapDeserializer.deserialize(p, ctxt);
}
return mapObject(p, ctxt);
case JsonTokenId.ID_START_ARRAY:
if (ctxt.isEnabled(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) {
return mapArrayToArray(p, ctxt);
}
if (_listDeserializer != null) {
return _listDeserializer.deserialize(p, ctxt);
}
return mapArray(p, ctxt);
case JsonTokenId.ID_EMBEDDED_OBJECT:
return p.getEmbeddedObject();
case JsonTokenId.ID_STRING:
if (_stringDeserializer != null) {
return _stringDeserializer.deserialize(p, ctxt);
}
return p.getText();
case JsonTokenId.ID_NUMBER_INT:
if (_numberDeserializer != null) {
return _numberDeserializer.deserialize(p, ctxt);
}
/* Caller may want to get all integral values returned as {@link java.math.BigInteger},
* or {@link java.lang.Long} for consistency
*/
if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) {
return _coerceIntegral(p, ctxt);
}
return p.getNumberValue(); // should be optimal, whatever it is
case JsonTokenId.ID_NUMBER_FLOAT:
if (_numberDeserializer != null) {
return _numberDeserializer.deserialize(p, ctxt);
}
// Need to allow overriding the behavior regarding which type to use
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
return p.getDecimalValue();
}
// as per [databind#1453] should not assume Double but:
return p.getNumberValue();
case JsonTokenId.ID_TRUE:
return Boolean.TRUE;
case JsonTokenId.ID_FALSE:
return Boolean.FALSE;
case JsonTokenId.ID_NULL: // 08-Nov-2016, tatu: yes, occurs
return null;
// case JsonTokenId.ID_END_ARRAY: // invalid
default:
}
return ctxt.handleUnexpectedToken(Object.class, p);
}
@Override
public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
TypeDeserializer typeDeserializer) throws IOException
{
switch (p.getCurrentTokenId()) {
// First: does it look like we had type id wrapping of some kind?
case JsonTokenId.ID_START_ARRAY:
case JsonTokenId.ID_START_OBJECT:
case JsonTokenId.ID_FIELD_NAME:
// Output can be as JSON Object, Array or scalar: no way to know at this point:
return typeDeserializer.deserializeTypedFromAny(p, ctxt);
case JsonTokenId.ID_EMBEDDED_OBJECT:
return p.getEmbeddedObject();
/* Otherwise we probably got a "native" type (ones that map
* naturally and thus do not need or use type ids)
*/
case JsonTokenId.ID_STRING:
if (_stringDeserializer != null) {
return _stringDeserializer.deserialize(p, ctxt);
}
return p.getText();
case JsonTokenId.ID_NUMBER_INT:
if (_numberDeserializer != null) {
return _numberDeserializer.deserialize(p, ctxt);
}
// May need coercion to "bigger" types:
if (ctxt.hasSomeOfFeatures(F_MASK_INT_COERCIONS)) {
return _coerceIntegral(p, ctxt);
}
return p.getNumberValue(); // should be optimal, whatever it is
case JsonTokenId.ID_NUMBER_FLOAT:
if (_numberDeserializer != null) {
return _numberDeserializer.deserialize(p, ctxt);
}
if (ctxt.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
return p.getDecimalValue();
}
return p.getNumberValue();
case JsonTokenId.ID_TRUE:
return Boolean.TRUE;
case JsonTokenId.ID_FALSE:
return Boolean.FALSE;
case JsonTokenId.ID_NULL: // should not get this far really but...
return null;
default:
}
return ctxt.handleUnexpectedToken(Object.class, p);
}
private static boolean ignoreUnknownEnums(DeserializationContext context) {
return context.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL);
}
@Override
public StackTraceElement deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
JsonToken t = p.getCurrentToken();
// Must get an Object
if (t == JsonToken.START_OBJECT) {
String className = "", methodName = "", fileName = "";
// Java 9 adds couple more things
String moduleName = null, moduleVersion = null;
String classLoaderName = null;
int lineNumber = -1;
while ((t = p.nextValue()) != JsonToken.END_OBJECT) {
String propName = p.getCurrentName();
// TODO: with Java 8, convert to switch
if ("className".equals(propName)) {
className = p.getText();
} else if ("classLoaderName".equals(propName)) {
classLoaderName = p.getText();
} else if ("fileName".equals(propName)) {
fileName = p.getText();
} else if ("lineNumber".equals(propName)) {
if (t.isNumeric()) {
lineNumber = p.getIntValue();
} else {
lineNumber = _parseIntPrimitive(p, ctxt);
}
} else if ("methodName".equals(propName)) {
methodName = p.getText();
} else if ("nativeMethod".equals(propName)) {
// no setter, not passed via constructor: ignore
} else if ("moduleName".equals(propName)) {
moduleName = p.getText();
} else if ("moduleVersion".equals(propName)) {
moduleVersion = p.getText();
} else if ("declaringClass".equals(propName)
|| "format".equals(propName)) {
// 01-Nov-2017: [databind#1794] Not sure if we should but... let's prune it for now
;
} else {
handleUnknownProperty(p, ctxt, _valueClass, propName);
}
p.skipChildren(); // just in case we might get structured values
}
return constructValue(ctxt, className, methodName, fileName, lineNumber,
moduleName, moduleVersion, classLoaderName);
} else if (t == JsonToken.START_ARRAY && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
p.nextToken();
final StackTraceElement value = deserialize(p, ctxt);
if (p.nextToken() != JsonToken.END_ARRAY) {
handleMissingEndArrayForSingle(p, ctxt);
}
return value;
}
return (StackTraceElement) ctxt.handleUnexpectedToken(_valueClass, p);
}
@SuppressWarnings("unchecked")
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt,
Object result)
throws IOException {
// Ok: must point to START_ARRAY (or equivalent)
if (!p.isExpectedStartArrayToken()) {
return handleNonArray(p, ctxt, (Collection<Object>) result);
}
// [databind#631]: Assign current value, to be accessible by custom serializers
p.setCurrentValue(result);
JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
CollectionReferringAccumulator referringAccumulator =
(valueDes.getObjectIdReader() == null) ? null :
new CollectionReferringAccumulator(_containerType.getContentType().getRawClass(), (Collection<Object>) result);
JsonToken t;
while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
try {
Object value;
if (t == JsonToken.VALUE_NULL) {
if (_skipNullValues) {
continue;
}
value = _nullProvider.getNullValue(ctxt);
} else if (typeDeser == null) {
value = valueDes.deserialize(p, ctxt);
} else {
value = valueDes.deserializeWithType(p, ctxt, typeDeser);
}
if (referringAccumulator != null) {
referringAccumulator.add(value);
} else {
((Collection<Object>) result).add(value);
}
} catch (UnresolvedForwardReference reference) {
if (referringAccumulator == null) {
throw JsonMappingException
.from(p, "Unresolved forward reference but no identity info", reference);
}
Referring ref = referringAccumulator.handleUnresolvedReference(reference);
reference.getRoid().appendReferring(ref);
} catch (Exception e) {
boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
if (!wrap) {
ClassUtil.throwIfRTE(e);
}
throw JsonMappingException.wrapWithPath(e, result, ((Collection<Object>) result).size());
}
}
return result;
}
private static boolean acceptEmptyStringAsNull(DeserializationContext context) {
return context.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
}
@Override
public Collection<Object> deserialize(JsonParser p, DeserializationContext ctxt,
Collection<Object> result)
throws IOException {
// Ok: must point to START_ARRAY (or equivalent)
if (!p.isExpectedStartArrayToken()) {
return result;
}
// [databind#631]: Assign current value, to be accessible by custom serializers
p.setCurrentValue(result);
JsonDeserializer<Object> valueDes = _valueDeserializer;
final TypeDeserializer typeDeser = _valueTypeDeserializer;
CollectionReferringAccumulator referringAccumulator =
(valueDes.getObjectIdReader() == null) ? null :
new CollectionReferringAccumulator(_containerType.getContentType().getRawClass(), result);
JsonToken t;
while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
try {
Object value;
if (t == JsonToken.VALUE_NULL) {
if (_skipNullValues) {
continue;
}
value = _nullProvider.getNullValue(ctxt);
} else if (typeDeser == null) {
value = valueDes.deserialize(p, ctxt);
} else {
value = valueDes.deserializeWithType(p, ctxt, typeDeser);
}
if (referringAccumulator != null) {
referringAccumulator.add(value);
} else {
result.add(value);
}
} catch (UnresolvedForwardReference reference) {
if (referringAccumulator == null) {
throw JsonMappingException
.from(p, "Unresolved forward reference but no identity info", reference);
}
ReadableObjectId.Referring ref = referringAccumulator.handleUnresolvedReference(reference);
reference.getRoid().appendReferring(ref);
} catch (Exception e) {
boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
if (!wrap) {
ClassUtil.throwIfRTE(e);
}
throw JsonMappingException.wrapWithPath(e, result, result.size());
}
}
return result;
}
@Override
public YearMonth deserialize(JsonParser parser, DeserializationContext context) throws IOException
{
if (parser.hasToken(JsonToken.VALUE_STRING)) {
String string = parser.getText().trim();
if (string.length() == 0) {
if (!isLenient()) {
return _failForNotLenient(parser, context, JsonToken.VALUE_STRING);
}
return null;
}
try {
return YearMonth.parse(string, _formatter);
} catch (DateTimeException e) {
return _handleDateTimeFormatException(context, e, _formatter, string);
}
}
if (parser.isExpectedStartArrayToken()) {
JsonToken t = parser.nextToken();
if (t == JsonToken.END_ARRAY) {
return null;
}
if ((t == JsonToken.VALUE_STRING || t == JsonToken.VALUE_EMBEDDED_OBJECT)
&& context.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
final YearMonth parsed = deserialize(parser, context);
if (parser.nextToken() != JsonToken.END_ARRAY) {
handleMissingEndArrayForSingle(parser, context);
}
return parsed;
}
if (t != JsonToken.VALUE_NUMBER_INT) {
_reportWrongToken(context, JsonToken.VALUE_NUMBER_INT, "years");
}
int year = parser.getIntValue();
int month = parser.nextIntValue(-1);
if (month == -1) {
if (!parser.hasToken(JsonToken.VALUE_NUMBER_INT)) {
_reportWrongToken(context, JsonToken.VALUE_NUMBER_INT, "months");
}
month = parser.getIntValue();
}
if (parser.nextToken() != JsonToken.END_ARRAY) {
throw context.wrongTokenException(parser, handledType(), JsonToken.END_ARRAY,
"Expected array to end");
}
return YearMonth.of(year, month);
}
if (parser.hasToken(JsonToken.VALUE_EMBEDDED_OBJECT)) {
return (YearMonth) parser.getEmbeddedObject();
}
return _handleUnexpectedToken(context, parser,
JsonToken.VALUE_STRING, JsonToken.START_ARRAY);
}
protected boolean shouldAdjustToContextTimezone(DeserializationContext context) {
return (_adjustToContextTZOverride != null) ? _adjustToContextTZOverride :
context.isEnabled(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
}
@Override
public MonthDay deserialize(JsonParser parser, DeserializationContext context) throws IOException
{
if (parser.hasToken(JsonToken.VALUE_STRING)) {
String string = parser.getValueAsString().trim();
try {
if (_formatter == null) {
return MonthDay.parse(string);
}
return MonthDay.parse(string, _formatter);
} catch (DateTimeException e) {
return _handleDateTimeFormatException(context, e, _formatter, string);
}
}
if (parser.isExpectedStartArrayToken()) {
JsonToken t = parser.nextToken();
if (t == JsonToken.END_ARRAY) {
return null;
}
if ((t == JsonToken.VALUE_STRING || t == JsonToken.VALUE_EMBEDDED_OBJECT)
&& context.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
final MonthDay parsed = deserialize(parser, context);
if (parser.nextToken() != JsonToken.END_ARRAY) {
handleMissingEndArrayForSingle(parser, context);
}
return parsed;
}
if (t != JsonToken.VALUE_NUMBER_INT) {
_reportWrongToken(context, JsonToken.VALUE_NUMBER_INT, "month");
}
int month = parser.getIntValue();
int day = parser.nextIntValue(-1);
if (day == -1) {
if (!parser.hasToken(JsonToken.VALUE_NUMBER_INT)) {
_reportWrongToken(context, JsonToken.VALUE_NUMBER_INT, "day");
}
day = parser.getIntValue();
}
if (parser.nextToken() != JsonToken.END_ARRAY) {
throw context.wrongTokenException(parser, handledType(), JsonToken.END_ARRAY,
"Expected array to end");
}
return MonthDay.of(month, day);
}
if (parser.hasToken(JsonToken.VALUE_EMBEDDED_OBJECT)) {
return (MonthDay) parser.getEmbeddedObject();
}
return _handleUnexpectedToken(context, parser,
JsonToken.VALUE_STRING, JsonToken.START_ARRAY);
}
@Override
public LocalDate deserialize(JsonParser parser, DeserializationContext context) throws IOException
{
if (parser.hasToken(JsonToken.VALUE_STRING)) {
String string = parser.getText().trim();
if (string.length() == 0) {
if (!isLenient()) {
return _failForNotLenient(parser, context, JsonToken.VALUE_STRING);
}
return null;
}
// as per [datatype-jsr310#37], only check for optional (and, incorrect...) time marker 'T'
// if we are using default formatter
DateTimeFormatter format = _formatter;
try {
if (format == DEFAULT_FORMATTER) {
// JavaScript by default includes time in JSON serialized Dates (UTC/ISO instant format).
if (string.length() > 10 && string.charAt(10) == 'T') {
if (string.endsWith("Z")) {
return LocalDateTime.ofInstant(Instant.parse(string), ZoneOffset.UTC).toLocalDate();
} else {
return LocalDate.parse(string, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
}
}
return LocalDate.parse(string, format);
} catch (DateTimeException e) {
return _handleDateTimeFormatException(context, e, format, string);
}
}
if (parser.isExpectedStartArrayToken()) {
JsonToken t = parser.nextToken();
if (t == JsonToken.END_ARRAY) {
return null;
}
if (context.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
&& (t == JsonToken.VALUE_STRING || t==JsonToken.VALUE_EMBEDDED_OBJECT)) {
final LocalDate parsed = deserialize(parser, context);
if (parser.nextToken() != JsonToken.END_ARRAY) {
handleMissingEndArrayForSingle(parser, context);
}
return parsed;
}
if (t == JsonToken.VALUE_NUMBER_INT) {
int year = parser.getIntValue();
int month = parser.nextIntValue(-1);
int day = parser.nextIntValue(-1);
if (parser.nextToken() != JsonToken.END_ARRAY) {
throw context.wrongTokenException(parser, handledType(), JsonToken.END_ARRAY,
"Expected array to end");
}
return LocalDate.of(year, month, day);
}
context.reportInputMismatch(handledType(),
"Unexpected token (%s) within Array, expected VALUE_NUMBER_INT",
t);
}
if (parser.hasToken(JsonToken.VALUE_EMBEDDED_OBJECT)) {
return (LocalDate) parser.getEmbeddedObject();
}
// 06-Jan-2018, tatu: Is this actually safe? Do users expect such coercion?
if (parser.hasToken(JsonToken.VALUE_NUMBER_INT)) {
// issue 58 - also check for NUMBER_INT, which needs to be specified when serializing.
if (_shape == JsonFormat.Shape.NUMBER_INT || isLenient()) {
return LocalDate.ofEpochDay(parser.getLongValue());
}
return _failForNotLenient(parser, context, JsonToken.VALUE_STRING);
}
return _handleUnexpectedToken(context, parser, "Expected array or string.");
}