On Sun, May 27, 2018 at 5:58 AM, Kezhu Wang <[email protected]> wrote:
> The implementation of serialization and deserialization of java 8 time has
> several spots surprising me at first glance, I list here for discussion and
> feedbacks.

Yes. Handling is inconsistent in places, both with respect to Java 8
date/time types, and with respect to
other common date/time types (JDK pre-Java8, Joda). This is unfortunate.

One big challenge at this point is that due to handling working the
way it does, there are backwards-compatibility
concerns to consider. While it is true that JSON is used a lot in
cross-language/platform interchange, it is also true
that Jackson-to-Jackson usage is quite common.

On plus side, we can make bigger changes with Jackson 3.0, development
of which has started and is the version for
`master`. Conversely, I think most changes should not occur with 2.x.
But there are some exceptions...

> * For nanosecond resolution timestamps, current implementation uses
> decimals. I thought JSON is an universal data-exchange format, not
> jackson-to-jackson, this java and jackson specific behavior makes it hard to
> cooperate with implementations in other language. For short, we should no
> invent language specific convention in JSON. This behavior is enabled by
> default in current implementation.  Following is quotes from docs and codes.
>
>> Granularity of timestamps is controlled through the companion features
>> SerializationFeature#WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS and
>> DeserializationFeature#READ_DATE_TIMESTAMPS_AS_NANOSECONDS. For
>> serialization, timestamps are written as fractional numbers (decimals),
>> where the number is seconds and the decimal is fractional seconds, if
>> WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS is enabled (it is by default), with
>> resolution as fine as nanoseconds depending on the underlying JDK
>> implementation. If WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS is disabled,
>> timestamps are written as a whole number of milliseconds. At deserialization
>> time, decimal numbers are always read as fractional second timestamps with
>> up-to-nanosecond resolution, since the meaning of the decimal is
>> unambiguous. The more ambiguous integer types are read as fractional seconds
>> without a decimal point if READ_DATE_TIMESTAMPS_AS_NANOSECONDS is enabled
>> (it is by default), and otherwise they are read as milliseconds.  ----
>> https://github.com/FasterXML/jackson-modules-java8/tree/master/datetime
>
>
>
> // In DurationDeserializer.java
> case JsonTokenId.ID_NUMBER_INT:
>
> if(context.isEnabled(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS))
> {
>         return Duration.ofSeconds(parser.getLongValue());
>     }
>     return Duration.ofMillis(parser.getLongValue());
>
> // In DurationSerializer.java
> if (useNanoseconds(provider)) {
>     generator.writeNumber(DecimalUtils.toBigDecimal(duration.getSeconds(),
> duration.getNano());
> } else {
>     generator.writeNumber(duration.toMillis());
> }
>
>
> I recommend we write nanosecond resolution timestamps as integer value which
> is number in JSON and `long` in Java. If the value overflow underlying
> storage, just exception. If clients worry about this, they can switch to ISO
> 8601 for date.
>
> * Current implementation of `DurationSerializer` uses
> `WRITE_DATES_AS_TIMESTAMPS` for time duration serialization while
> `WRITE_DURATIONS_AS_TIMESTAMPS` is ignored totally. When I turn off
> `WRITE_DATES_AS_TIMESTAMPS` and turn on `WRITE_DURATION_AS_TIMESTAMPS`,
> current implementation uses `Duration.toString`. I use `@JsonFormat(shape =
> JsonFormat.Shape.NUMBER)` to circumvent this for now. I open a pull
> request(https://github.com/FasterXML/jackson-modules-java8/pull/75) about
> this in github. `DurationSerializer` uses
> `WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS` also, but there is no
> `WRITE_DURATION_TIMESTAMPS_AS_NANOSECONDS` feature for now. May be we should
> separate features for duration from date.

Yes, I think that makes sense. One practical question is just that of
how feature set should evolve for Jackson 3.0.
There is limitation both semantically (we should keep set of general
`SerializationFeature` / `DeserializationFeature`
general, and ideally not something specific to individual datatype, or
maybe even class of datatypes) and
practical ones (as things are, current implementation is actually
limited to 31 features per enum -- easy enough to extend
to 63, but I think this is not as much of a limitation as at that
point set becomes unwieldy from user perspective).

But I think that `Shape` configuration should work better in some
ways. With 3.x, I plan to add "category" of types, so
you could apply Shape config override for "all date/time types" -- and
since it will be hierarchy, can further have
intermediate categories like "duration types".

> * Current implementation defaults date and duration to timestamp with
> nanosecond resolution. I think default options should be suitable for common
> use cases. I recommend we use ISO 8601 date and integer duration with both
> millisecond resolution. ISO 8601 format date should be more readable than
> large integer value and has no overflow concern and millisecond resolution
> is more commonly used in practice. This is just personal opinion.


I think all of above are fair comments worth discussing.

For me the main challenge is that I do not feel like an expert in
date/time handling.
Java 8 datetime module was a contribution, and I think its author
(Nick Williams) would
probably be the best authority, although there have been a few active
contributors who
have also left their mark.


-+ Tatu +-

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to