I am facing an issue with configuring the Jackson ObjectMapper to deserialize java.sql.Timestamp.
In particular, the issue is that deserialization with a mapper that was initialized via ObjectMapper mapper = new ObjectMapper() works, while using a globally registered one that is dependency injected by spring does not. I do not know how the global one is declared, which makes it hard to debug which setting exactly makes it not work.
So my question is basically what ObjectMapper configurations/modules are exactly required to deserialize java.sql.Timestamp?
Note that I do not want to define any (field specific format) annotations on MyClass!
Class to deserialize
import java.sql.Timestamp;
public class MyClass {
private Timestamp startTime;
}
Json
{
"startTime":"2025-07-08T09:29:54.000+0000"
}
Test case
@SpringBootTest
public class DeserializationTest {
@Autowired
ObjectMapper injectedMapper;
@Test
public void foo() throws JsonMappingException, JsonProcessingException {
ObjectMapper localMapper = new ObjectMapper();
String json = "{\"startTime\":\"2025-07-08T09:29:54.000+0000\"}";
localMapper.readValue(json, MyClass.class); // this works
injectedMapper.readValue(json, MyClass.class); // this fails with InvalidFormat
assertTrue(true);
}
}
The injectedMapper.readValue(...) invocation fails with InvalidFormat Cannot deserialize value of type 'java.lang.Long' from String "2025-07-08T09:29:54.000+0000": not a valid 'java.lang.Long' value
I know there are already a couple of questions in this direction, but the answers typically recommend annotations on the class that should be deserialized or have custom timestamp formats. I am looking for a configuration on the ObjectMapper definition instead.
Edit:
I also don't want to register custom deserializers, since the fact that new ObjectMapper().readValue(...) successfully deserializes the json tells me that there must be out-of-the-box configuration that makes this work without anything custom
Edit2:
Comparison of ObjectMapper settings:
new ObjectMapper()
Modules:
-none-
Serialization Features:
WRAP_ROOT_VALUE -> false
INDENT_OUTPUT -> false
FAIL_ON_EMPTY_BEANS -> true (enabled by default)
FAIL_ON_SELF_REFERENCES -> true (enabled by default)
WRAP_EXCEPTIONS -> true (enabled by default)
FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS -> true (enabled by default)
WRITE_SELF_REFERENCES_AS_NULL -> false
CLOSE_CLOSEABLE -> false
FLUSH_AFTER_WRITE_VALUE -> true (enabled by default)
WRITE_DATES_AS_TIMESTAMPS -> true (enabled by default)
WRITE_DATE_KEYS_AS_TIMESTAMPS -> false
WRITE_DATES_WITH_ZONE_ID -> false
WRITE_DATES_WITH_CONTEXT_TIME_ZONE -> true (enabled by default)
WRITE_DURATIONS_AS_TIMESTAMPS -> true (enabled by default)
WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS -> false
WRITE_ENUMS_USING_TO_STRING -> false
WRITE_ENUMS_USING_INDEX -> false
WRITE_ENUM_KEYS_USING_INDEX -> false
WRITE_NULL_MAP_VALUES -> true (enabled by default)
WRITE_EMPTY_JSON_ARRAYS -> true (enabled by default)
WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED -> false
WRITE_BIGDECIMAL_AS_PLAIN -> false
WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS -> true (enabled by default)
ORDER_MAP_ENTRIES_BY_KEYS -> false
EAGER_SERIALIZER_FETCH -> true (enabled by default)
USE_EQUALITY_FOR_OBJECT_ID -> false
Deserialization Features:
USE_BIG_DECIMAL_FOR_FLOATS -> false
USE_BIG_INTEGER_FOR_INTS -> false
USE_LONG_FOR_INTS -> false
USE_JAVA_ARRAY_FOR_JSON_ARRAY -> false
FAIL_ON_UNKNOWN_PROPERTIES -> true (enabled by default)
FAIL_ON_NULL_FOR_PRIMITIVES -> false
FAIL_ON_NUMBERS_FOR_ENUMS -> false
FAIL_ON_INVALID_SUBTYPE -> true (enabled by default)
FAIL_ON_READING_DUP_TREE_KEY -> false
FAIL_ON_IGNORED_PROPERTIES -> false
FAIL_ON_UNRESOLVED_OBJECT_IDS -> true (enabled by default)
FAIL_ON_MISSING_CREATOR_PROPERTIES -> false
FAIL_ON_NULL_CREATOR_PROPERTIES -> false
FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY -> true (enabled by default)
FAIL_ON_TRAILING_TOKENS -> false
WRAP_EXCEPTIONS -> true (enabled by default)
ACCEPT_SINGLE_VALUE_AS_ARRAY -> false
UNWRAP_SINGLE_VALUE_ARRAYS -> false
UNWRAP_ROOT_VALUE -> false
ACCEPT_EMPTY_STRING_AS_NULL_OBJECT -> false
ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT -> false
ACCEPT_FLOAT_AS_INT -> true (enabled by default)
READ_ENUMS_USING_TO_STRING -> false
READ_UNKNOWN_ENUM_VALUES_AS_NULL -> false
READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE -> false
READ_DATE_TIMESTAMPS_AS_NANOSECONDS -> true (enabled by default)
ADJUST_DATES_TO_CONTEXT_TIME_ZONE -> true (enabled by default)
EAGER_DESERIALIZER_FETCH -> true (enabled by default)
Autowired one:
Modules:
com.fasterxml.jackson.datatype.jdk8.Jdk8Module
jackson-datatype-jsr310
jackson-module-kotlin
jackson-module-parameter-names
org.springframework.boot.jackson.JsonComponentModule
Spring Data Geo Mixins
Serialization Features:
WRAP_ROOT_VALUE -> false
INDENT_OUTPUT -> false
FAIL_ON_EMPTY_BEANS -> true (enabled by default)
FAIL_ON_SELF_REFERENCES -> true (enabled by default)
WRAP_EXCEPTIONS -> true (enabled by default)
FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS -> true (enabled by default)
WRITE_SELF_REFERENCES_AS_NULL -> false
CLOSE_CLOSEABLE -> false
FLUSH_AFTER_WRITE_VALUE -> true (enabled by default)
WRITE_DATES_AS_TIMESTAMPS -> false (enabled by default)
WRITE_DATE_KEYS_AS_TIMESTAMPS -> false
WRITE_DATES_WITH_ZONE_ID -> false
WRITE_DATES_WITH_CONTEXT_TIME_ZONE -> true (enabled by default)
WRITE_DURATIONS_AS_TIMESTAMPS -> false (enabled by default)
WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS -> false
WRITE_ENUMS_USING_TO_STRING -> false
WRITE_ENUMS_USING_INDEX -> false
WRITE_ENUM_KEYS_USING_INDEX -> false
WRITE_NULL_MAP_VALUES -> true (enabled by default)
WRITE_EMPTY_JSON_ARRAYS -> true (enabled by default)
WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED -> false
WRITE_BIGDECIMAL_AS_PLAIN -> false
WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS -> true (enabled by default)
ORDER_MAP_ENTRIES_BY_KEYS -> false
EAGER_SERIALIZER_FETCH -> true (enabled by default)
USE_EQUALITY_FOR_OBJECT_ID -> false
Deserialization Features:
USE_BIG_DECIMAL_FOR_FLOATS -> false
USE_BIG_INTEGER_FOR_INTS -> false
USE_LONG_FOR_INTS -> false
USE_JAVA_ARRAY_FOR_JSON_ARRAY -> false
FAIL_ON_UNKNOWN_PROPERTIES -> false (enabled by default)
FAIL_ON_NULL_FOR_PRIMITIVES -> false
FAIL_ON_NUMBERS_FOR_ENUMS -> false
FAIL_ON_INVALID_SUBTYPE -> true (enabled by default)
FAIL_ON_READING_DUP_TREE_KEY -> false
FAIL_ON_IGNORED_PROPERTIES -> false
FAIL_ON_UNRESOLVED_OBJECT_IDS -> true (enabled by default)
FAIL_ON_MISSING_CREATOR_PROPERTIES -> false
FAIL_ON_NULL_CREATOR_PROPERTIES -> false
FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY -> true (enabled by default)
FAIL_ON_TRAILING_TOKENS -> false
WRAP_EXCEPTIONS -> true (enabled by default)
ACCEPT_SINGLE_VALUE_AS_ARRAY -> false
UNWRAP_SINGLE_VALUE_ARRAYS -> false
UNWRAP_ROOT_VALUE -> false
ACCEPT_EMPTY_STRING_AS_NULL_OBJECT -> false
ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT -> false
ACCEPT_FLOAT_AS_INT -> true (enabled by default)
READ_ENUMS_USING_TO_STRING -> false
READ_UNKNOWN_ENUM_VALUES_AS_NULL -> false
READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE -> false
READ_DATE_TIMESTAMPS_AS_NANOSECONDS -> true (enabled by default)
ADJUST_DATES_TO_CONTEXT_TIME_ZONE -> true (enabled by default)
EAGER_DESERIALIZER_FETCH -> true (enabled by default)
Just the properties that differ:
Modules:
-none-
-------
Modules:
com.fasterxml.jackson.datatype.jdk8.Jdk8Module
jackson-datatype-jsr310
jackson-module-kotlin
jackson-module-parameter-names
org.springframework.boot.jackson.JsonComponentModule
Spring Data Geo Mixins
Serialization Features:
WRITE_DATES_AS_TIMESTAMPS -> true (enabled by default)
WRITE_DURATIONS_AS_TIMESTAMPS -> true (enabled by default)
-------
WRITE_DATES_AS_TIMESTAMPS -> false (enabled by default)
WRITE_DURATIONS_AS_TIMESTAMPS -> false (enabled by default)
Deserialization Features:
FAIL_ON_UNKNOWN_PROPERTIES -> true (enabled by default)
-------
FAIL_ON_UNKNOWN_PROPERTIES -> false (enabled by default)
I would have expected other deserialization features that would be different, but it's only FAIL_ON_UNKNOWN_PROPERTIES.
I also tried registering the modules on the local mapper, expecting that this may break the deserialization for it then, but it didn't
java.timeinstead. Timestamp is a very badly designed class (well anything that extends java.util.Date for that matter) and should be avoided.new ObjectMapper().readValue(...)is able to successfully deserialize toTimestamptells me that it is possible to configure theObjectMapperwithout any custom annotations or serializers. I'll edit my question againObjectMapper, to see how Spring configures it?