-
Notifications
You must be signed in to change notification settings - Fork 123
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