com.fasterxml.jackson.databind.util.ISO8601DateFormat is deprecated since 2.9 but I couldn't find any information about how to replace its current usage while upgrading.
So far, I checked the following locations:
But no luck...
I suspect that I could probably just delete objectMapper.setDateFormat(new ISO8601DateFormat()); and be fine but I wanted to double-check.
So this is a bug report against the documentation, not the code. If it can be safely removed and dates are still serialized as ISO-8601 strings then this should be mentioned somewhere.
Correct: StdDateFormat has been used everywhere at least with 2.8 (I did not see where it would have been used originally), and it is the default formatter/parser.
And it supports (one of many) ISO-8601 format, one that JDK date/time types have supported.
You are correct in that you should just remove that setDateFormat() call: StdDateFormat is used by default.
I'll see if I can find more information on last Jackson version that actually used ISO8601DateFormat.
If I had realized its lack of use earlier, I'd have first deprecated it in 2.8; but due to big rewrite of ISO-8601 handling, lack of direct use, I assumed (... incorrectly it seems) that no one was using it.
Ok. So, the class has been include since 2.0 at least (Jackson moved to github at that version), but was never actually used by rest of databind code. I do not recall its history: I do not usually include utility classes that are not bound or accessed by API. It is possible this might have been due to refactoring since 1.9.
If there is any documentation that suggest use of this class I would want to update it.
I can't tell you where I originally found a reference to that class but I'm 100% sure it dates back to 2010 or 2011. From there it was copy-pasted to every new ObjectMapper configuration because "Of course we want ISO-8601". ¯\_(ツ)_/¯
No problem at all, I just wanted to check back before removing it all over the code base.
Thanks for the fast reply!
@huxi lol. Yes, apologies for breaking change here -- I can totally see why it would make sense from user perspective, esp. considering that documentation has always been bit sparse.
So: yes, this mysterious class is gone and should not be needed.
For posterity, here's an example of serializing to iso8601 without the ISO8601DateFormat class from the jackson tests themselves: https://github.com/FasterXML/jackson-databind/blob/b1aa8e300519076b2140a2bfd73bf0eac73191de/src/test/java/com/fasterxml/jackson/databind/ser/jdk/DateSerializationTest.java#L118
Looks like default StdDateFormat doesn't format date-time the same as ISO8601DateFormat.
I found this while integrating with a 3rd party API which uses Swagger spec.
In Swagger they have a date-time data type:
date-time– the date-time notation as defined by RFC 3339, section 5.6, for example,2017-07-21T17:32:28Z
According to the RFC the timezone information must follow this BNF:
time-numoffset = ("+" / "-") time-hour ":" time-minute
time-offset = "Z" / time-numoffset
...
full-time = partial-time time-offset
Notice the ":" in time-numoffset is not optional, but default StdDateFormat is omitting it, so Swagger implementations will refuse such dates.
Not sure if that's an issue in RFC or Swagger, but I cannot really use the default StdDateFormat. With ISO8601DateFormat everything works as expected, but as I understand the class is deprecated for removal.
Migrating from Jackson 2.8.11 to 2.9.8, and am finding that for a given date, StdDateFormat.format(date) returns 2019-03-20T21:56:29.533+0000 while ISO8601DateFormat(date) returns 2019-03-20T21:56:29Z. How do I force the ISO8601DateFormat behavior when using StdDateFormat?
Note that the format returned by ISO8601DateFormat is listed as the default in the JavaDocs.
@rhwood
So, the way to customize formatting of output is either by overriding DateFormat used:
ObjectMapper.setDateFormat()
and defining (for example) properly configured SimpleDateFormat of your choice, or by specifying format String for type(s) you want it to apply:
mapper.configOverride(Date.class)
.setFormat(JsonFormat.Value.forPattern("yyyy.dd.MM"));
in which case a SimpleDateFormat is constructed with the format String (in case of "old" JDK types), or, with Joda and Java 8 date/time, using their formatter equivalents.
StdDateFormat has limited configurability itself, and is not meant to be directly configured; for output it supports specific format indicated (javadoc should of course include correct information, I'll update that for 2.10 javadocs).
@dmitrygusev There is addition of StdDateFormat.withColonInTimeZone(boolean) (see #1744) that will be in 2.10 (and was actually included in 2.9.1, which is against typical versioning constraints -- added since it was deemed critical problem for some users).
So it is possible to force inclusion of colon in timezone, to work with systems that mandate it. Note that JDK itself has had different versions in this regard so discrepancies have backwards compatibility root.
Ok, so Javadoc might be correct I think, although it may be misleading: it states that "Format String" looks like yyyy-MM-dd'T'HH:mm:ss.SSSZ, where Z refers to offset without colons, as per:
https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
I also found that StdDateFormat cannot be used as is in place of ISO8601DateFormat because Go cannot parse StdDateFormat output. To be exact, Go doesn't support parsing timezone offset without colon. Using withColonInTimeZone(true) fixes the issue.
It is because in section 5.6. Internet Date/Time Format of RFC 3339 colon is not optional:
time-numoffset = ("+" / "-") time-hour ":" time-minute
So, while both variants (with and without colon) are valid ISO-8601, using colon improves interoperability with other software that doesn't implement full ISO-8601 spec but only a subset recommended by RFC 3339 for internet communication.
Most helpful comment
Looks like default
StdDateFormatdoesn't format date-time the same asISO8601DateFormat.I found this while integrating with a 3rd party API which uses Swagger spec.
In Swagger they have a
date-timedata type:According to the RFC the timezone information must follow this BNF:
Notice the
":"intime-numoffsetis not optional, but defaultStdDateFormatis omitting it, so Swagger implementations will refuse such dates.Not sure if that's an issue in RFC or Swagger, but I cannot really use the default
StdDateFormat. WithISO8601DateFormateverything works as expected, but as I understand the class is deprecated for removal.