- 
                Notifications
    You must be signed in to change notification settings 
- Fork 124
Closed
Labels
pr-welcomeIssue for which progress most likely if someone submits a Pull RequestIssue for which progress most likely if someone submits a Pull Request
Description
I have a scenario where I would like to de-serialize epoch milis, and serialize with a @JsonFormat annotation. In essence:
  final ObjectMapper mapper = new ObjectMapper()
      .disable(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)
      .disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)
      .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
      .setTimeZone(TimeZone.getTimeZone("UTC"))
      .findAndRegisterModules();
  final Instant instant = Instant.ofEpochMilli(123456);
  @Test
  public void test() throws JsonProcessingException {
    assertEquals("{\"time\":\"1970-01-01T00:02:03.456+0000\"}", mapper.writeValueAsString(new TimeHolderWithFormat(instant)));
    assertEquals(instant, mapper.readValue("{\"time\":123456}", TimeHolder.class).time);
    assertEquals(instant, mapper.readValue("{\"time\":\"123456\"}", TimeHolder.class).time);
    assertEquals(instant, mapper.readValue("{\"time\":123456}", TimeHolderWithFormat.class).time);
    assertEquals(instant, mapper.readValue("{\"time\":\"123456\"}", TimeHolderWithFormat.class).time);
  }
  
  static class TimeHolder {
    private Instant time;
    public void setTime(Instant time) {
      this.time = time;
    }
    // Getter ommited
  }
  static class TimeHolderWithFormat {
    private Instant time;
    // Constructors ommited
    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    public void setTime(Instant time) {
      this.time = time;
    }
    // Getter ommited
  }This will fail on the last assertion with:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.Instant` from String "123456": Failed to deserialize java.time.Instant: (java.time.format.DateTimeParseException) Text '123456' could not be parsed at index 0
 at [Source: (String)"{"time":"123456"}"; line: 1, column: 9] (through reference chain: com.example.app.AppTest$TimeHolderWithFormat["time"])
There is an apparent inconsistency in the way Jackson de-serializes numbers that are shaped as a string into an instant.
- When not providing a custom date format, quoted numbers are treated as epoch milis/nanos
- When not providing a custom date, quoted numbers are assumed to be handled by the pattern.
Lines 267 to 277 in 8693cf9
| // only check for other parsing modes if we are using default formatter | |
| if (_formatter == DateTimeFormatter.ISO_INSTANT || | |
| _formatter == DateTimeFormatter.ISO_OFFSET_DATE_TIME || | |
| _formatter == DateTimeFormatter.ISO_ZONED_DATE_TIME) { | |
| // 22-Jan-2016, [datatype-jsr310#16]: Allow quoted numbers too | |
| int dots = _countPeriods(string); | |
| if (dots >= 0) { // negative if not simple number | |
| try { | |
| if (dots == 0) { | |
| return _fromLong(ctxt, NumberInput.parseLong(string)); | |
| } | 
There is however no way to construct a pattern that handles both ISO dates and epoch milis/nanos. Would it be possible to add a feature toggle here?
Details:
- Reproducer: https://github.com/mpkorstanje/jackson-jsonformat-and-epoch-milis
- Jackson version: 2.14.1
Metadata
Metadata
Assignees
Labels
pr-welcomeIssue for which progress most likely if someone submits a Pull RequestIssue for which progress most likely if someone submits a Pull Request