How to set format of string for java.time.Instant using objectMapper?
Solution 1
For those looking to parse Java 8 timestamps. You need a recent version of jackson-datatype-jsr310
in your POM and have the following module registered:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
To test this code
@Test
void testSeliarization() throws IOException {
String expectedJson = "{\"parseDate\":\"2018-12-04T18:47:38.927Z\"}";
MyPojo pojo = new MyPojo(ZonedDateTime.parse("2018-12-04T18:47:38.927Z"));
// serialization
assertThat(objectMapper.writeValueAsString(pojo)).isEqualTo(expectedJson);
// deserialization
assertThat(objectMapper.readValue(expectedJson, MyPojo.class)).isEqualTo(pojo);
}
Solution 2
Here's some Kotlin code of formatting Instant
, so it does not contain milliseconds, you can use custom date formatters
ObjectMapper().apply {
val javaTimeModule = JavaTimeModule()
javaTimeModule.addSerializer(Instant::class.java, Iso8601WithoutMillisInstantSerializer())
registerModule(javaTimeModule)
disable(WRITE_DATES_AS_TIMESTAMPS)
}
private class Iso8601WithoutMillisInstantSerializer
: InstantSerializer(InstantSerializer.INSTANCE, false, DateTimeFormatterBuilder().appendInstant(0).toFormatter())
Solution 3
You need to add below dependency
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.6.5</version>
</dependency>
And then register the modules as below :
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.findAndRegisterModules();
Solution 4
In my case it was enough to register the JavaTimeModule:
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
objectMapper.registerModule(module);
messageObject = objectMapper.writeValueAsString(event);
In the event Object I have a field of type Instant.
In the deserialization you also need to register the java time module:
ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule());
Event event = objectMapper.readValue(record.value(), Event.class);
Solution 5
If using Spring, and spring-web
is on the classpath, you can create an ObjectMapper
using the Jackson2ObjectMapperBuilder
. It registers the following commonly used modules within the method registerWellKnownModulesIfAvailable
.
com.fasterxml.jackson.datatype.jdk8.Jdk8Module
com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
com.fasterxml.jackson.datatype.joda.JodaModule
com.fasterxml.jackson.module.kotlin.KotlinModule
Some of these modules have been merged into Jackson 3; see here.
Uladzislau Kaminski
Chief Information Officer at Oyper Inc. Experience with Java since 2014 year.
Updated on November 12, 2020Comments
-
Uladzislau Kaminski over 3 years
I have an entity with
java.time.Instant
for created data field:@Getter @Setter @AllArgsConstructor @NoArgsConstructor @EqualsAndHashCode public class Item { private String id; private String url; private Instant createdDate; }
I am using
com.fasterxml.jackson.databind.ObjectMapper
to save item to Elasticsearch as JSON:bulkRequestBody.append(objectMapper.writeValueAsString(item));
ObjectMapper
serializes this field as an object:"createdDate": { "epochSecond": 1502643595, "nano": 466000000 }
I was trying the annotation
@JsonFormat(shape = JsonFormat.Shape.STRING)
but it doesn't work for me.My question is how I could serialize this field as
2010-05-30 22:15:52
string?