Skip to content

Commit 22acd59

Browse files
samwillcowtowncoder
authored andcommitted
Fixes #148: Deserializes Dates, Times, and DateTimes using DateTimeFormatter with ResolverStyle.STRICT when JsonFormat lenient = false (#151)
1 parent 2ef7c25 commit 22acd59

File tree

4 files changed

+94
-1
lines changed

4 files changed

+94
-1
lines changed

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

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.IOException;
44
import java.time.format.DateTimeFormatter;
55
import java.time.format.DateTimeFormatterBuilder;
6+
import java.time.format.ResolverStyle;
67
import java.util.Locale;
78

89
import com.fasterxml.jackson.annotation.JsonFormat;
@@ -137,6 +138,11 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
137138
} else {
138139
df = builder.toFormatter(locale);
139140
}
141+
142+
if (format.hasLenient() && !format.isLenient()) {
143+
df = df.withResolverStyle(ResolverStyle.STRICT);
144+
}
145+
140146
//Issue #69: For instant serializers/deserializers we need to configure the formatter with
141147
//a time zone picked up from JsonFormat annotation, otherwise serialization might not work
142148
if (format.hasTimeZone()) {

datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalDateDeserTest.java

+25
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import java.time.temporal.Temporal;
1616
import java.util.Map;
1717

18+
import com.fasterxml.jackson.annotation.OptBoolean;
19+
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
1820
import org.junit.Test;
1921

2022
import com.fasterxml.jackson.annotation.JsonFormat;
@@ -54,6 +56,15 @@ public ShapeWrapper() { }
5456
public ShapeWrapper(LocalDate v) { date = v; }
5557
}
5658

59+
final static class StrictWrapper {
60+
@JsonFormat(pattern="yyyy-MM-dd",
61+
lenient = OptBoolean.FALSE)
62+
public LocalDate value;
63+
64+
public StrictWrapper() { }
65+
public StrictWrapper(LocalDate v) { value = v; }
66+
}
67+
5768
/*
5869
/**********************************************************
5970
/* Deserialization from Int array representation
@@ -295,6 +306,20 @@ public void testCustomFormat() throws Exception
295306
assertEquals(28, date.getDayOfMonth());
296307
}
297308

309+
310+
/*
311+
/**********************************************************
312+
/* Strict Custom format
313+
/**********************************************************
314+
*/
315+
316+
// for [modules-java8#148]
317+
@Test(expected = InvalidFormatException.class)
318+
public void testStrictCustomFormat() throws Exception
319+
{
320+
StrictWrapper w = MAPPER.readValue("{\"value\":\"2019-11-31\"}", StrictWrapper.class);
321+
}
322+
298323
/*
299324
/**********************************************************************
300325
/* Case-insensitive tests

datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalDateTimeDeserTest.java

+36
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.fasterxml.jackson.annotation.JsonFormat;
2020
import com.fasterxml.jackson.annotation.JsonFormat.Feature;
2121
import com.fasterxml.jackson.annotation.JsonFormat.Value;
22+
import com.fasterxml.jackson.annotation.OptBoolean;
2223
import com.fasterxml.jackson.core.JsonParser;
2324
import com.fasterxml.jackson.core.JsonProcessingException;
2425
import com.fasterxml.jackson.core.JsonToken;
@@ -52,6 +53,15 @@ public class LocalDateTimeDeserTest
5253
private final static ObjectReader READER = MAPPER.readerFor(LocalDateTime.class);
5354
private final TypeReference<Map<String, LocalDateTime>> MAP_TYPE_REF = new TypeReference<Map<String, LocalDateTime>>() { };
5455

56+
final static class StrictWrapper {
57+
@JsonFormat(pattern="yyyy-MM-dd HH:mm",
58+
lenient = OptBoolean.FALSE)
59+
public LocalDateTime value;
60+
61+
public StrictWrapper() { }
62+
public StrictWrapper(LocalDateTime v) { value = v; }
63+
}
64+
5565
/*
5666
/**********************************************************
5767
/* Tests for deserializing from int array
@@ -458,6 +468,32 @@ public void testDeserializationCaseInsensitiveDisabled_InvalidDate() throws Thro
458468
}
459469
}
460470

471+
/*
472+
/**********************************************************************
473+
/* Strict JsonFormat tests
474+
/**********************************************************************
475+
*/
476+
477+
// [modules-java8#148]: handle strict deserializaiton for date/time
478+
@Test(expected = InvalidFormatException.class)
479+
public void testStrictCustomFormatInvalidDate() throws Exception
480+
{
481+
StrictWrapper w = MAPPER.readValue("{\"value\":\"2019-11-31 15:45\"}", StrictWrapper.class);
482+
}
483+
484+
@Test(expected = InvalidFormatException.class)
485+
public void testStrictCustomFormatInvalidTime() throws Exception
486+
{
487+
StrictWrapper w = MAPPER.readValue("{\"value\":\"2019-11-30 25:45\"}", StrictWrapper.class);
488+
}
489+
490+
@Test(expected = InvalidFormatException.class)
491+
public void testStrictCustomFormatInvalidDateAndTime() throws Exception
492+
{
493+
StrictWrapper w = MAPPER.readValue("{\"value\":\"2019-11-31 25:45\"}", StrictWrapper.class);
494+
}
495+
496+
461497
private void expectSuccess(ObjectReader reader, Object exp, String json) throws IOException {
462498
final LocalDateTime value = reader.readValue(aposToQuotes(json));
463499
assertNotNull("The value should not be null.", value);

datetime/src/test/java/com/fasterxml/jackson/datatype/jsr310/deser/LocalTimeDeserTest.java

+27-1
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@
3131
import static org.junit.Assert.fail;
3232

3333
import com.fasterxml.jackson.annotation.JsonFormat;
34+
import com.fasterxml.jackson.annotation.OptBoolean;
3435
import com.fasterxml.jackson.core.JsonProcessingException;
3536
import com.fasterxml.jackson.core.type.TypeReference;
3637
import com.fasterxml.jackson.databind.DeserializationFeature;
3738
import com.fasterxml.jackson.databind.ObjectMapper;
3839
import com.fasterxml.jackson.databind.ObjectReader;
40+
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
3941
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
4042
import com.fasterxml.jackson.datatype.jsr310.MockObjectConfiguration;
4143
import com.fasterxml.jackson.datatype.jsr310.ModuleTestBase;
@@ -44,9 +46,19 @@
4446

4547
public class LocalTimeDeserTest extends ModuleTestBase
4648
{
47-
private ObjectReader reader = newMapper().readerFor(LocalTime.class);
49+
private final static ObjectMapper MAPPER = newMapper();
50+
private ObjectReader reader = MAPPER.readerFor(LocalTime.class);
4851
private final TypeReference<Map<String, LocalTime>> MAP_TYPE_REF = new TypeReference<Map<String, LocalTime>>() { };
4952

53+
final static class StrictWrapper {
54+
@JsonFormat(pattern="HH:mm",
55+
lenient = OptBoolean.FALSE)
56+
public LocalDateTime value;
57+
58+
public StrictWrapper() { }
59+
public StrictWrapper(LocalDateTime v) { value = v; }
60+
}
61+
5062
@Test
5163
public void testDeserializationAsTimestamp01() throws Exception
5264
{
@@ -258,6 +270,20 @@ public void testStrictDeserializeFromEmptyString() throws Exception {
258270
objectReader.readValue(valueFromEmptyStr);
259271
}
260272

273+
/*
274+
/**********************************************************************
275+
/* Strict JsonFormat tests
276+
/**********************************************************************
277+
*/
278+
279+
// [modules-java8#148]: handle strict deserializaiton for date/time
280+
281+
@Test(expected = InvalidFormatException.class)
282+
public void testStrictCustomFormatInvalidTime() throws Exception
283+
{
284+
StrictWrapper w = MAPPER.readValue("{\"value\":\"25:45\"}", StrictWrapper.class);
285+
}
286+
261287
private void expectFailure(String aposJson) throws Throwable {
262288
try {
263289
reader.readValue(aposToQuotes(aposJson));

0 commit comments

Comments
 (0)