Skip to content

Commit

Permalink
Minor refactoring after #148 to streamline handling
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Nov 2, 2019
1 parent 8b35502 commit e93ab34
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,6 @@ protected InstantDeserializer<T> withDateFormat(DateTimeFormatter dtf) {

@Override
protected InstantDeserializer<T> withLeniency(Boolean leniency) {
if (_isLenient == !Boolean.FALSE.equals(leniency)) {
return this;
}
return new InstantDeserializer<T>(this, _formatter, leniency);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Feature;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.util.ClassUtil;

@SuppressWarnings("serial")
public abstract class JSR310DateTimeDeserializerBase<T>
Expand All @@ -26,21 +26,6 @@ public abstract class JSR310DateTimeDeserializerBase<T>
{
protected final DateTimeFormatter _formatter;

/**
* Flag that indicates what leniency setting is enabled for this deserializer (either
* due {@link JsonFormat} annotation on property or class, or due to per-type
* "config override", or from global settings): leniency/strictness has effect
* on accepting some non-default input value representations (such as integer values
* for dates).
*<p>
* Note that global default setting is for leniency to be enabled, for Jackson 2.x,
* and has to be explicitly change to force strict handling: this is to keep backwards
* compatibility with earlier versions.
*
* @since 2.10
*/
protected final boolean _isLenient;

/**
* Setting that indicates the {@Link JsonFormat.Shape} specified for this deserializer
* as a {@link JsonFormat.Shape} annotation on property or class, or due to per-type
Expand All @@ -57,17 +42,15 @@ public abstract class JSR310DateTimeDeserializerBase<T>
protected JSR310DateTimeDeserializerBase(Class<T> supportedType, DateTimeFormatter f) {
super(supportedType);
_formatter = f;
_isLenient = true;
_shape = null;
}

/**
* @since 2.11
*/
public JSR310DateTimeDeserializerBase(Class<T> supportedType, DateTimeFormatter f, Boolean leniency) {
super(supportedType);
super(supportedType, leniency);
_formatter = f;
_isLenient = !Boolean.FALSE.equals(leniency);
_shape = null;
}

Expand All @@ -78,7 +61,6 @@ protected JSR310DateTimeDeserializerBase(JSR310DateTimeDeserializerBase<T> base,
DateTimeFormatter f) {
super(base);
_formatter = f;
_isLenient = base._isLenient;
_shape = base._shape;
}

Expand All @@ -87,43 +69,48 @@ protected JSR310DateTimeDeserializerBase(JSR310DateTimeDeserializerBase<T> base,
*/
protected JSR310DateTimeDeserializerBase(JSR310DateTimeDeserializerBase<T> base,
Boolean leniency) {
super(base);
super(base, leniency);
_formatter = base._formatter;
_isLenient = !Boolean.FALSE.equals(leniency);
_shape = base._shape;
}

/**
* @since 2.11
*/
protected JSR310DateTimeDeserializerBase(JSR310DateTimeDeserializerBase<T> base,
Shape shape) {
Shape shape) {
super(base);
_formatter = base._formatter;
_shape = shape;
_isLenient = base._isLenient;
}

protected abstract JSR310DateTimeDeserializerBase<T> withDateFormat(DateTimeFormatter dtf);

/**
* @since 2.10
*/
@Override
protected abstract JSR310DateTimeDeserializerBase<T> withLeniency(Boolean leniency);

/**
* @since 2.11
*/
protected abstract JSR310DateTimeDeserializerBase<T> withShape(Shape shape);


@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType());
JSR310DateTimeDeserializerBase<?> deser = this;
if (format != null) {
// 17-Aug-2019, tatu: For 2.10 let's start considering leniency/strictness too
if (format.hasLenient()) {
Boolean leniency = format.getLenient();
if (leniency != null) {
deser = deser.withLeniency(leniency);
}
}
if (format.hasPattern()) {
final String pattern = format.getPattern();
final Locale locale = format.hasLocale() ? format.getLocale() : ctxt.getLocale();
Expand All @@ -139,25 +126,19 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
df = builder.toFormatter(locale);
}

if (format.hasLenient() && !format.isLenient()) {
// [#148]: allow strict parsing
if (!deser.isLenient()) {
df = df.withResolverStyle(ResolverStyle.STRICT);
}

//Issue #69: For instant serializers/deserializers we need to configure the formatter with
// [#69]: For instant serializers/deserializers we need to configure the formatter with
//a time zone picked up from JsonFormat annotation, otherwise serialization might not work
if (format.hasTimeZone()) {
df = df.withZone(format.getTimeZone().toZoneId());
}
deser = deser.withDateFormat(df);
}
// 17-Aug-2019, tatu: For 2.10 let's start considering leniency/strictness too
if (format.hasLenient()) {
Boolean leniency = format.getLenient();
if (leniency != null) {
deser = deser.withLeniency(leniency);
}
}
//Issue #58: For LocalDate deserializers we need to configure the formatter with
// [#58]: For LocalDate deserializers we need to configure the formatter with
//a shape picked up from JsonFormat annotation, to decide if the value is EpochSeconds
JsonFormat.Shape shape = format.getShape();
if (shape != null && shape != _shape) {
Expand All @@ -168,15 +149,6 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
return deser;
}

/**
* @return {@code true} if lenient handling is enabled; {code false} if not (strict mode)
*
* @since 2.10
*/
protected boolean isLenient() {
return _isLenient;
}

private boolean acceptCaseInsensitiveValues(DeserializationContext ctxt, JsonFormat.Value format)
{
Boolean enabled = format.getFeature( Feature.ACCEPT_CASE_INSENSITIVE_VALUES);
Expand All @@ -193,13 +165,4 @@ protected void _throwNoNumericTimestampNeedTimeZone(JsonParser p, Deserializatio
"raw timestamp (%d) not allowed for `%s`: need additional information such as an offset or time-zone (see class Javadocs)",
p.getNumberValue(), handledType().getName());
}

@SuppressWarnings("unchecked")
protected T _failForNotLenient(JsonParser p, DeserializationContext ctxt,
JsonToken expToken) throws IOException
{
return (T) ctxt.handleUnexpectedToken(handledType(), expToken, p,
"Cannot deserialize instance of %s out of %s token: not allowed because 'strict' mode set for property or type (enable 'lenient' handling to allow)",
ClassUtil.nameOf(handledType()), p.currentToken());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ protected JSR310DeserializerBase(Class<T> supportedType,

protected JSR310DeserializerBase(JSR310DeserializerBase<T> base) {
super(base);
_isLenient = true;
_isLenient = base._isLenient;
}

protected JSR310DeserializerBase(JSR310DeserializerBase<T> base, Boolean leniency) {
Expand Down Expand Up @@ -155,7 +155,6 @@ protected <R> R _handleUnexpectedToken(DeserializationContext context,
}
}

@SuppressWarnings("unchecked")
protected <R> R _handleUnexpectedToken(DeserializationContext context,
JsonParser parser, JsonToken... expTypes) throws JsonMappingException {
return _handleUnexpectedToken(context, parser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ public void testCustomFormat() throws Exception
@Test(expected = InvalidFormatException.class)
public void testStrictCustomFormat() throws Exception
{
StrictWrapper w = MAPPER.readValue("{\"value\":\"2019-11-31\"}", StrictWrapper.class);
/*StrictWrapper w =*/ MAPPER.readValue("{\"value\":\"2019-11-31\"}", StrictWrapper.class);
}

/*
Expand Down Expand Up @@ -379,9 +379,9 @@ public void testDeserializationCaseInsensitiveDisabled_InvalidDate() throws Thro
/*
* Tests for issue 58 - NUMBER_INT should be specified when deserializing
* LocalDate as EpochDays
*
/**********************************************************************
*/
/**********************************************************************
*/
@Test
public void testLenientDeserializeFromNumberInt() throws Exception {
ObjectMapper mapper = newMapper();
Expand Down Expand Up @@ -420,7 +420,7 @@ public void testStrictDeserializeFromString() throws Exception
/**********************************************************************
/* Helper methods
/**********************************************************************
*/
*/
private void expectFailure(ObjectReader reader, String json) throws Throwable {
try {
reader.readValue(aposToQuotes(json));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ public void testStrictDeserializeFromEmptyString() throws Exception {
objectReader.readValue(valueFromEmptyStr);
}

/*
/*
/**********************************************************************
/* Strict JsonFormat tests
/**********************************************************************
Expand All @@ -280,7 +280,7 @@ public void testStrictDeserializeFromEmptyString() throws Exception {
@Test(expected = InvalidFormatException.class)
public void testStrictCustomFormatInvalidTime() throws Exception
{
StrictWrapper w = MAPPER.readValue("{\"value\":\"25:45\"}", StrictWrapper.class);
/*StrictWrapper w =*/ MAPPER.readValue("{\"value\":\"25:45\"}", StrictWrapper.class);
}

private void expectFailure(String aposJson) throws Throwable {
Expand Down

0 comments on commit e93ab34

Please sign in to comment.