Open
Description
Describe the bug
ObjectMapper#readValue(String)
seems to preserve all nine digits of an Instant
's decimal, but ObjectMapper#readTree(JsonParser)
does not.
Version information
Jackson 2.12.1
To Reproduce
ObjectMapper mapper = new ObjectMapper();
{
mapper.registerModule(new JavaTimeModule());
}
Instant issuedAt = Instant.ofEpochSecond(1234567890).plusNanos(123456789);
Map<String, Instant> attributes = new HashMap<>();
{
attributes.put("iat", issuedAt);
}
@Test
void passes() throws Exception {
String serialized = mapper.writeValueAsString(attributes);
Map<String, Instant> deserialized = mapper.readValue(serialized, new TypeReference<>() {});
assertThat(deserialized.get("iat")).isEqualTo(issuedAt);
}
@Test
void fails() throws Exception {
String serialized = mapper.writeValueAsString(attributes);
JsonParser parser = mapper.createParser(serialized);
JsonNode mapNode = mapper.readTree(parser);
Map<String, Object> deserialized = new LinkedHashMap<>();
Iterable<Map.Entry<String, JsonNode>> fields = mapNode::fields;
for (Map.Entry<String, JsonNode> field : fields) {
deserialized.put(field.getKey(), mapper.readValue(field.getValue().traverse(mapper), Instant.class));
}
assertThat(deserialized.get("iat")).isEqualTo(issuedAt);
}
The second test fails with:
Expecting:
<2009-02-13T23:31:30.123456700Z>
to be equal to:
<2009-02-13T23:31:30.123456789Z>
but was not.
Expected :2009-02-13T23:31:30.123456789Z
Actual :2009-02-13T23:31:30.123456700Z
Additional context
The failure case is derived from a custom deserializer in our project.
Ideally, I'd like readTree
to retain the Instant
's precision in the same way that ObjectMapper#readValue
does when it deserializes a Map
that contains Instant
s, though I'd be happy with advice on how to change my approach in my deserializer instead.
I realize also that USE_BIG_DECIMAL_FOR_FLOATS
addresses this issue, but I'd prefer to avoid that, since others import our module.