Skip to content

Commit b00073e

Browse files
committed
Start work on #129
1 parent bb8ad7f commit b00073e

13 files changed

+187
-80
lines changed

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/InstantDeserializer.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,19 @@ protected InstantDeserializer(InstantDeserializer<T> base, Boolean adjustToConte
152152
}
153153

154154
@Override
155-
protected JsonDeserializer<T> withDateFormat(DateTimeFormatter dtf) {
155+
protected InstantDeserializer<T> withDateFormat(DateTimeFormatter dtf) {
156156
if (dtf == _formatter) {
157157
return this;
158158
}
159159
return new InstantDeserializer<T>(this, dtf);
160160
}
161161

162+
// !!! TODO: lenient vs strict?
163+
@Override
164+
protected InstantDeserializer<T> withLeniency(Boolean leniency) {
165+
return this;
166+
}
167+
162168
@SuppressWarnings("unchecked")
163169
@Override
164170
public T deserialize(JsonParser parser, DeserializationContext context) throws IOException

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/JSR310DateTimeDeserializerBase.java

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import com.fasterxml.jackson.annotation.JsonFormat;
88
import com.fasterxml.jackson.core.JsonParser;
9+
import com.fasterxml.jackson.core.JsonToken;
910
import com.fasterxml.jackson.databind.BeanProperty;
1011
import com.fasterxml.jackson.databind.DeserializationContext;
1112
import com.fasterxml.jackson.databind.JsonDeserializer;
@@ -19,19 +20,60 @@ public abstract class JSR310DateTimeDeserializerBase<T>
1920
{
2021
protected final DateTimeFormatter _formatter;
2122

22-
protected JSR310DateTimeDeserializerBase(Class<T> supportedType, DateTimeFormatter f)
23-
{
23+
/**
24+
* Flag that indicates what leniency setting is enabled for this deserializer (either
25+
* due {@link JsonFormat} annotation on property or class, or due to per-type
26+
* "config override", or from global settings): leniency/strictness has effect
27+
* on accepting some non-default input value representations (such as integer values
28+
* for dates).
29+
*<p>
30+
* Note that global default setting is for leniency to be enabled, for Jackson 2.x,
31+
* and has to be explicitly change to force strict handling: this is to keep backwards
32+
* compatibility with earlier versions.
33+
*
34+
* @since 2.10
35+
*/
36+
protected final boolean _isLenient;
37+
38+
protected JSR310DateTimeDeserializerBase(Class<T> supportedType, DateTimeFormatter f) {
2439
super(supportedType);
2540
_formatter = f;
41+
_isLenient = true;
2642
}
2743

28-
protected abstract JsonDeserializer<T> withDateFormat(DateTimeFormatter dtf);
44+
/**
45+
* @since 2.10
46+
*/
47+
protected JSR310DateTimeDeserializerBase(JSR310DateTimeDeserializerBase<T> base,
48+
DateTimeFormatter f) {
49+
super(base);
50+
_formatter = f;
51+
_isLenient = base._isLenient;
52+
}
53+
54+
/**
55+
* @since 2.10
56+
*/
57+
protected JSR310DateTimeDeserializerBase(JSR310DateTimeDeserializerBase<T> base,
58+
Boolean leniency) {
59+
super(base);
60+
_formatter = base._formatter;
61+
_isLenient = !Boolean.FALSE.equals(leniency);
62+
}
63+
64+
protected abstract JSR310DateTimeDeserializerBase<T> withDateFormat(DateTimeFormatter dtf);
65+
66+
/**
67+
* @since 2.10
68+
*/
69+
protected abstract JSR310DateTimeDeserializerBase<T> withLeniency(Boolean leniency);
2970

3071
@Override
3172
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
3273
BeanProperty property) throws JsonMappingException
3374
{
3475
JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType());
76+
JSR310DateTimeDeserializerBase<?> deser = this;
3577
if (format != null) {
3678
if (format.hasPattern()) {
3779
final String pattern = format.getPattern();
@@ -47,18 +89,42 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
4789
if (format.hasTimeZone()) {
4890
df = df.withZone(format.getTimeZone().toZoneId());
4991
}
50-
return withDateFormat(df);
92+
deser = deser.withDateFormat(df);
93+
}
94+
// 17-Aug-2019, tatu: For 2.10 let's start considering leniency/strictness too
95+
if (format.hasLenient()) {
96+
Boolean leniency = format.getLenient();
97+
if (leniency != null) {
98+
deser = deser.withLeniency(leniency);
99+
}
51100
}
52101
// any use for TimeZone?
53102
}
54-
return this;
55-
}
103+
return deser;
104+
}
56105

106+
/**
107+
* @return {@code true} if lenient handling is enabled; {code false} if not (strict mode)
108+
*
109+
* @since 2.10
110+
*/
111+
protected boolean isLenient() {
112+
return _isLenient;
113+
}
114+
57115
protected void _throwNoNumericTimestampNeedTimeZone(JsonParser p, DeserializationContext ctxt)
58116
throws IOException
59117
{
60118
ctxt.reportInputMismatch(handledType(),
61119
"raw timestamp (%d) not allowed for `%s`: need additional information such as an offset or time-zone (see class Javadocs)",
62120
p.getNumberValue(), handledType().getName());
63121
}
122+
123+
@SuppressWarnings("unchecked")
124+
protected T _failForNotLenient(JsonParser p, DeserializationContext ctxt,
125+
JsonToken expToken) throws IOException
126+
{
127+
return (T) ctxt.handleUnexpectedToken(handledType(), expToken, p,
128+
"not allowed because 'strict' mode set for property or type (enabled 'lenient' handling to allow)");
129+
}
64130
}

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/JSR310DeserializerBase.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,17 @@ abstract class JSR310DeserializerBase<T> extends StdScalarDeserializer<T>
3838
{
3939
private static final long serialVersionUID = 1L;
4040

41-
protected JSR310DeserializerBase(Class<T> supportedType)
42-
{
41+
protected JSR310DeserializerBase(Class<T> supportedType) {
4342
super(supportedType);
4443
}
4544

45+
/**
46+
* @since 2.10
47+
*/
48+
protected JSR310DeserializerBase(JSR310DeserializerBase<?> base) {
49+
super(base);
50+
}
51+
4652
@Override
4753
public Object deserializeWithType(JsonParser parser, DeserializationContext context,
4854
TypeDeserializer typeDeserializer)

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalDateDeserializer.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,11 @@
2727
import com.fasterxml.jackson.core.*;
2828
import com.fasterxml.jackson.databind.DeserializationContext;
2929
import com.fasterxml.jackson.databind.DeserializationFeature;
30-
import com.fasterxml.jackson.databind.JsonDeserializer;
3130

3231
/**
3332
* Deserializer for Java 8 temporal {@link LocalDate}s.
3433
*
3534
* @author Nick Williams
36-
* @since 2.2.0
3735
*/
3836
public class LocalDateDeserializer extends JSR310DateTimeDeserializerBase<LocalDate>
3937
{
@@ -43,19 +41,38 @@ public class LocalDateDeserializer extends JSR310DateTimeDeserializerBase<LocalD
4341

4442
public static final LocalDateDeserializer INSTANCE = new LocalDateDeserializer();
4543

46-
private LocalDateDeserializer() {
44+
protected LocalDateDeserializer() {
4745
this(DEFAULT_FORMATTER);
4846
}
4947

5048
public LocalDateDeserializer(DateTimeFormatter dtf) {
5149
super(LocalDate.class, dtf);
5250
}
5351

52+
/**
53+
* Since 2.10
54+
*/
55+
public LocalDateDeserializer(LocalDateDeserializer base, DateTimeFormatter dtf) {
56+
super(base, dtf);
57+
}
58+
59+
/**
60+
* Since 2.10
61+
*/
62+
protected LocalDateDeserializer(LocalDateDeserializer base, Boolean leniency) {
63+
super(base, leniency);
64+
}
65+
5466
@Override
55-
protected JsonDeserializer<LocalDate> withDateFormat(DateTimeFormatter dtf) {
56-
return new LocalDateDeserializer(dtf);
67+
protected LocalDateDeserializer withDateFormat(DateTimeFormatter dtf) {
68+
return new LocalDateDeserializer(this, dtf);
5769
}
58-
70+
71+
@Override
72+
protected LocalDateDeserializer withLeniency(Boolean leniency) {
73+
return new LocalDateDeserializer(this, leniency);
74+
}
75+
5976
@Override
6077
public LocalDate deserialize(JsonParser parser, DeserializationContext context) throws IOException
6178
{
@@ -116,6 +133,9 @@ public LocalDate deserialize(JsonParser parser, DeserializationContext context)
116133
}
117134
// 06-Jan-2018, tatu: Is this actually safe? Do users expect such coercion?
118135
if (parser.hasToken(JsonToken.VALUE_NUMBER_INT)) {
136+
if (!isLenient()) {
137+
return _failForNotLenient(parser, context, JsonToken.VALUE_STRING);
138+
}
119139
return LocalDate.ofEpochDay(parser.getLongValue());
120140
}
121141
return _handleUnexpectedToken(context, parser, "Expected array or string.");

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalDateTimeDeserializer.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import com.fasterxml.jackson.core.JsonTokenId;
2929
import com.fasterxml.jackson.databind.DeserializationContext;
3030
import com.fasterxml.jackson.databind.DeserializationFeature;
31-
import com.fasterxml.jackson.databind.JsonDeserializer;
3231

3332
/**
3433
* Deserializer for Java 8 temporal {@link LocalDateTime}s.
@@ -54,10 +53,16 @@ public LocalDateTimeDeserializer(DateTimeFormatter formatter) {
5453
}
5554

5655
@Override
57-
protected JsonDeserializer<LocalDateTime> withDateFormat(DateTimeFormatter formatter) {
56+
protected LocalDateTimeDeserializer withDateFormat(DateTimeFormatter formatter) {
5857
return new LocalDateTimeDeserializer(formatter);
5958
}
6059

60+
// !!! TODO: lenient vs strict?
61+
@Override
62+
protected LocalDateTimeDeserializer withLeniency(Boolean leniency) {
63+
return this;
64+
}
65+
6166
@Override
6267
public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException
6368
{

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalTimeDeserializer.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,11 @@
2525
import com.fasterxml.jackson.core.JsonToken;
2626
import com.fasterxml.jackson.databind.DeserializationContext;
2727
import com.fasterxml.jackson.databind.DeserializationFeature;
28-
import com.fasterxml.jackson.databind.JsonDeserializer;
2928

3029
/**
3130
* Deserializer for Java 8 temporal {@link LocalTime}s.
3231
*
3332
* @author Nick Williams
34-
* @since 2.2.0
3533
*/
3634
public class LocalTimeDeserializer extends JSR310DateTimeDeserializerBase<LocalTime>
3735
{
@@ -50,10 +48,16 @@ public LocalTimeDeserializer(DateTimeFormatter formatter) {
5048
}
5149

5250
@Override
53-
protected JsonDeserializer<LocalTime> withDateFormat(DateTimeFormatter formatter) {
51+
protected LocalTimeDeserializer withDateFormat(DateTimeFormatter formatter) {
5452
return new LocalTimeDeserializer(formatter);
5553
}
56-
54+
55+
// !!! TODO: lenient vs strict?
56+
@Override
57+
protected LocalTimeDeserializer withLeniency(Boolean leniency) {
58+
return this;
59+
}
60+
5761
@Override
5862
public LocalTime deserialize(JsonParser parser, DeserializationContext context) throws IOException
5963
{

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/MonthDayDeserializer.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import com.fasterxml.jackson.core.JsonToken;
1010
import com.fasterxml.jackson.databind.DeserializationContext;
1111
import com.fasterxml.jackson.databind.DeserializationFeature;
12-
import com.fasterxml.jackson.databind.JsonDeserializer;
1312

1413
/**
1514
* Deserializer for Java 8 temporal {@link MonthDay}s.
@@ -25,10 +24,16 @@ public MonthDayDeserializer(DateTimeFormatter formatter) {
2524
}
2625

2726
@Override
28-
protected JsonDeserializer<MonthDay> withDateFormat(DateTimeFormatter dtf) {
27+
protected MonthDayDeserializer withDateFormat(DateTimeFormatter dtf) {
2928
return new MonthDayDeserializer(dtf);
3029
}
31-
30+
31+
// !!! TODO: lenient vs strict?
32+
@Override
33+
protected MonthDayDeserializer withLeniency(Boolean leniency) {
34+
return this;
35+
}
36+
3237
@Override
3338
public MonthDay deserialize(JsonParser parser, DeserializationContext context) throws IOException
3439
{

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/OffsetTimeDeserializer.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,16 @@ protected OffsetTimeDeserializer(DateTimeFormatter dtf) {
4545
}
4646

4747
@Override
48-
protected JsonDeserializer<OffsetTime> withDateFormat(DateTimeFormatter dtf) {
48+
protected OffsetTimeDeserializer withDateFormat(DateTimeFormatter dtf) {
4949
return new OffsetTimeDeserializer(dtf);
5050
}
51-
51+
52+
// !!! TODO: lenient vs strict?
53+
@Override
54+
protected OffsetTimeDeserializer withLeniency(Boolean leniency) {
55+
return this;
56+
}
57+
5258
@Override
5359
public OffsetTime deserialize(JsonParser parser, DeserializationContext context) throws IOException
5460
{

datetime/src/main/java/com/fasterxml/jackson/datatype/jsr310/deser/YearDeserializer.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import com.fasterxml.jackson.core.JsonParser;
2020
import com.fasterxml.jackson.core.JsonToken;
2121
import com.fasterxml.jackson.databind.DeserializationContext;
22-
import com.fasterxml.jackson.databind.JsonDeserializer;
2322

2423
import java.io.IOException;
2524
import java.time.DateTimeException;
@@ -30,7 +29,6 @@
3029
* Deserializer for Java 8 temporal {@link Year}s.
3130
*
3231
* @author Nick Williams
33-
* @since 2.2
3432
*/
3533
public class YearDeserializer extends JSR310DateTimeDeserializerBase<Year>
3634
{
@@ -48,10 +46,16 @@ public YearDeserializer(DateTimeFormatter formatter) {
4846
}
4947

5048
@Override
51-
protected JsonDeserializer<Year> withDateFormat(DateTimeFormatter dtf) {
49+
protected YearDeserializer withDateFormat(DateTimeFormatter dtf) {
5250
return new YearDeserializer(dtf);
5351
}
5452

53+
// !!! TODO: lenient vs strict?
54+
@Override
55+
protected YearDeserializer withLeniency(Boolean leniency) {
56+
return this;
57+
}
58+
5559
@Override
5660
public Year deserialize(JsonParser parser, DeserializationContext context) throws IOException
5761
{

0 commit comments

Comments
 (0)