FasterXML / jackson-future-ideas

Repository for SOLE PURPOSE of issue tracker and Wiki for NEW IDEAS. Please: NO BUG REPORTS.
18 stars 6 forks source link

Jackson 3 should serialise date/time classes in RFC 3339 / ISO 8601 interchange format by default #64

Closed tmoschou closed 2 years ago

tmoschou commented 2 years ago

Hello,

Thank you for your work on Jackson.

Could I suggest date/time classes (in particular java.time.*) serialise as RFC 3339 / ISO 8601 interchange format by default for Jackson 3, and not as an epoch second, milli, micro or nano, etc.

It is the recommended practice by Google/Microsoft and many others (see below) that RFC 3339 / ISO 8601 be used for the serialisation format for date/times in JSON. It is also generally the default format used by java.time.* .toString() and .parse() methods.

ISO 8601, I would say, is a better format than an epoch as

Speaking from my experience, its seems quite common for developers less familiar with Jackson to accidentally forget to disable SerializationFeature.WRITE_DATES_AS_TIMESTAMPS and can become problematic maintaining compatibility; though can be mitigated specifying @JsonFormat(shape = STRING) on new fields.

Other frameworks may for instance try to do this already, for example Spring Boot's JacksonAutoConfiguration does this by default.

I did see https://github.com/FasterXML/jackson-future-ideas/wiki/JSTEP-2#changes-to-datetime-defaults and https://github.com/FasterXML/jackson-future-ideas/wiki/JSTEP-5 but it seems it hadn't come to a firm conclusion what the default behaviour for date time serialisation in Jackson should be.

Thanks for your consideration

References which consider RFC 3339 / ISO 8601 for datetime:

tmoschou commented 2 years ago

Additionally, DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE should switch the default from true to false in Jackson 3 to preserve and not discard the timezone information where it can (e.g. when deserialising into OffsetDateTime).

The current default in Jackson 2 does not adhere to the Principle of Least Surprise and very easy to not pick up.

OffsetDateTime odt1 = OffsetDateTime.parse("2020-01-01T00:00+09:30");
String json = mapper.writeValueAsString(odt)
OffsetDateTime odt2 = mapper.readValue(json, OffsetDateTime.class)
// 2019-12-31T14:30Z 😮

A user could easily call toInstant() or atZoneSameInstant() if required to adjust timezone.

Obviously if deserialising into a type that does not support zone offset (e.g. Instant), would have to to adjust to UTC.

https://github.com/FasterXML/jackson-modules-java8/issues/53

tmoschou commented 2 years ago

Closed in favour of discussion hosted at https://groups.google.com/g/jackson-dev/c/BfLjoaCF7fQ