For LocalDate and LocalDateTime deserialization, empty string is mapped to null by LocalDateDeserializer and LocalDateTimeDeserializer respectively. So something like {"date": null} can't be distinguished from {"date": ""}. From the view of a strict API, the latter is an error.
It would be good to add some feature to treat empty string as invalid format, that LocalDateDeserializer and LocalDateTimeDeserializer could report this as an error instead of mapping to null.
Perhaps use of
DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT
would work here, although my main concern is that since default value isfalse
, adding a check would make formerly accepted values invalid with 2.10...Alternative way would be to add a new option/feature in
JavaTimeModule
, where it could be locally enabled/disabled.
Now, given beytun's point about 'strict', perhaps another solution is to use the lenient/strict setting here? That is already used in LocalDateDeserializer to throw an exception:
if (parser.hasToken(JsonToken.VALUE_NUMBER_INT)) {
if (!isLenient()) {
return _failForNotLenient(parser, context, JsonToken.VALUE_STRING);
}
return LocalDate.ofEpochDay(parser.getLongValue());
}
Test case to illustrate issue:
private final TypeReference<Map<String, LocalDate>> MAP_TYPE_REF = new TypeReference<Map<String, LocalDate>>() { };
private final ObjectMapper LOCAL_DATE_MAPPER = newMapper();
private final ObjectReader LOCAL_DATE_READER = LOCAL_DATE_MAPPER.readerFor(MAP_TYPE_REF);
@Test
public void testDeserializationNullAndEmptyString() throws Exception {
String dateValAsNullStr = null;
String valueFromNullStr = LOCAL_DATE_MAPPER.writeValueAsString(asMap("date", dateValAsNullStr));
Map<String, LocalDate> actualMapFromNullStr = LOCAL_DATE_READER.readValue(valueFromNullStr);
assertNull(actualMapFromNullStr.get("date"));
String dateValAsEmptyStr = "";
String valueFromEmptyStr = LOCAL_DATE_MAPPER.writeValueAsString(asMap("date", dateValAsEmptyStr));
Map<String, LocalDate> actualMapFromEmptyStr = LOCAL_DATE_READER.readValue(valueFromEmptyStr);
// this test fails!
assertNotEquals(actualMapFromEmptyStr,actualMapFromNullStr);
}
Researching a bit, there doesn't seem to be anything in the spec that says not to do it as beytun suggests:
https://stackoverflow.com/questions/9619852/what-is-the-convention-in-json-for-empty-vs-null?noredirect=1&lq=1
https://www.ibm.com/support/knowledgecenter/SSTLXK_7.5.1/com.ibm.wbpm.wid.integ.doc/topics/rjsonnullunsempprops.htmlSpeaking of nulls, Tony Hoare calls this his "billion-dollar" mistake. Initially I disagreed but now I'm not so sure :)
https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/
--
You received this message because you are subscribed to the Google Groups "jackson-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jackson-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jackson-dev/f98b3a71-c408-4eb9-a029-743dcf1f73af%40googlegroups.com.
This email and any attachments to it (the "Communication") is, unless otherwise stated, confidential, may contain copyright material and is for the use only of the intended recipient. If you receive the Communication in error, please notify the sender immediately by return email, delete the Communication and the return e mail, and do not read, copy, retransmit or otherwise deal with it. Any views expressed in the Communication are those of the individual sender only, unless expressly stated to be those of Message4U Pty Ltd trading as MessageMedia or any of its related entities (together “MessageMedia”). MessageMedia does not accept liability in connection with the integrity of or errors in the Communication, computer virus, data corruption, interference or delay arising from or in respect of the Communication.
Using strict resolution will ensure that all parsed values are within the outer range of valid values for the field. Individual fields may be further processed for strictness.
For example, resolving year-month and day-of-month in the ISO calendar system using strict mode will ensure that the day-of-month is valid for the year-month, rejecting invalid values.
Using lenient resolution will resolve the values in an appropriate lenient manner. Individual fields will interpret this differently.
For example, lenient mode allows the month in the ISO calendar system to be outside the range 1 to 12. For example, month 15 is treated as being 3 months after month 12.
https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_LOCAL_TIME
https://docs.oracle.com/javase/8/docs/api/java/time/format/ResolverStyle.html#STRICT
Now, one question: Would 'strict' be the default in 3.0?
>2. Use `ACCEPT_EMPTY_STRING_AS_NULL_OBJECT` -- problem being that it
>is disabled by default, which is at odds with actual behavior.
To view this discussion on the web visit https://groups.google.com/d/msgid/jackson-dev/CAL4a10jPVf3q7-aZBBqeOP1O%2BSZt8b5WTi7DdSEAvzn0Njb0PA%40mail.gmail.com.