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.
