I have a class:
public class Test{
private String name;
private ZonedDateTime date1;
private ZonedDateTime date2;
and i also have a method to represent object in JSON format:
private String convertTestToJson(Test test) {
ObjectMapper mapper = new ObjectMapper();
try {
mapper.registerModule(new JavaTimeModule());
return mapper.writeValueAsString(test);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
When i creating the object i try to sout result in the console i got rightly json format with rigtly fields but time is represent in miliseconds :
{"reportType":"Test name","date1":1615978661.832223700,"date2":1615978661.837225400}
But i want to get date in normal format like year-month-day hour-minute-second-milis but when i remove this line: mapper.registerModule(new JavaTimeModule()); I got the exception:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.ZonedDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1276)
at com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer.serialize(UnsupportedTypeSerializer.java:35)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4487)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3742)
at com.mycroft.report.Report.convertReportToJson(Test.java:38)
at com.mycroft.report.Report.generateReport(Test.java:30)
at com.mycroft.Main.main(Main.java:21)
I also got in dependency :
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.12.2</version>
</dependency>
And the question is how i can represent date in right format, no in miliseconds?
Change your class as follows:
public class Test{
private String name;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
private ZonedDateTime date1;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
private ZonedDateTime date2;
This should resolve your problem.
Source: Spring Data JPA - ZonedDateTime format for json serialization
Related
["last_modified"])] with root cause
java.time.format.DateTimeParseException: Text '2018-06-06T13:19:53+00:00' could not be parsed, unparsed text found at index 19
The inbound format is 2018-06-06T13:19:53+00:00
It's a weird format.
I have tried the following:
public class XYZ {
#DateTimeFormat(pattern = "yyyy-MM-ddTHH:mm:ss+00:00", iso = ISO.DATE_TIME)
private LocalDateTime lastModified;
}
There is nothing stopping you from creating your own deserializer. A very naive example could be the following:
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
private static final String PATTERN = "yyyy-MM-dd'T'HH:mm:ss+00:00";
private final DateTimeFormatter formatter;
public LocalDateTimeDeserializer() {
this.formatter = DateTimeFormatter.ofPattern(PATTERN);
}
#Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return LocalDateTime.parse(p.getText(), formatter);
}
}
The only thing you need to notice is that you'll need to escape the 'T' by adding single quote around it.
With the deserializer in place you can simply annotate the field like so:
#JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime dateTime;
The inbound format is 2018-06-06T13:19:53+00:00
It's a weird format.
That's the ISO 8601 format, which is endorsed by the RFC 3339 and by the xkcd 1179:
The following should work as expected when receiving the values as query parameters:
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDate dateTime;
As 2018-06-06T13:19:53+00:00 represents a date and time with an offset from UTC, you'd better use OffsetDateTime rather than LocalDateTime:
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private OffsetDateTime dateTime;
Just ensure that + is encoded as %2B.
With Jackson, you could add the jackson-datatype-jsr310 dependency to your application. This module will provide you with serializers and deserializers for java.time types.
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
And then register the JavaTimeModule module in your ObjectMapper:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
Jackson will handle the serialization and deserialization for you.
If you are, for some reason, not interested in the offset from UTC and want to keep using LocalDateTime, you could extend the LocalDateTimeDeserializer provided by Jackson and use a custom DateTimeFormatter:
public class CustomLocalDateTimeDeserializer extends LocalDateTimeDeserializer {
public CustomLocalDateTimeDeserializer() {
super(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
}
}
Then annotate the LocalDateTime field as shown below:
#JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime dateTime;
The inbound format is 2018-06-06T13:19:53+00:00
If you're able to set the Date Format on your entire ObjectMapper, you could do the following:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
objectMapper.setDateFormat(df);
This is part of the examples from the SimpleDateFormat Javadocs
I'm trying to deserialize a String to LocalDateTime with Jackson but it doesn't work.
I have a data class with a LocalDateTime field:
#Data
public class Registration {
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private LocalDateTime timestamp;
}
I added the special Jackson datatype modules:
compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
The serialization works fine with:
new ObjectMapper().registerModule(new JavaTimeModule()).writeValueAsString(registration);
Result String:
{"timestamp":"2018-09-03 10:09:35"}
But the deserialization doesn't work with:
new ObjectMapper().registerModule(new JavaTimeModule()).readValue(json.traverse(), Registration.class)
As error I get:
Cannot deserialize value of type `java.time.LocalDateTime` from String "2018-09-03 10:09:35":
Failed to deserialize java.time.LocalDateTime:
(java.time.format.DateTimeParseException) Text '2018-09-03 10:09:35' could not be parsed:
Unable to obtain LocalDateTime from TemporalAccessor:
{MinuteOfHour=9, NanoOfSecond=0, SecondOfMinute=35, MicroOfSecond=0, MilliOfSecond=0, HourOfAmPm=10},
ISO resolved to 2018-09-03 of type java.time.format.Parsed
What am I missing? I'm confused that the serialization works but the deserialization doesn't.
MWE: (small gradle Java project)
Main.java:
import java.io.IOException;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class Main {
public static void main(String[] args) throws IOException {
Registration registration = new Registration();
registration.setTimestamp(LocalDateTime.now());
ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule());
String s = objectMapper.writeValueAsString(registration);
TreeNode treeNode = objectMapper.readTree(s);
//Fails here:
Registration registration1 = objectMapper.readValue(treeNode.traverse(), Registration.class);
System.out.println(registration1);
}
}
class Registration {
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private LocalDateTime timestamp;
public Registration() {
}
public LocalDateTime getTimestamp() {
return this.timestamp;
}
public void setTimestamp(LocalDateTime localDateTime) {
this.timestamp = localDateTime;
}
}
build.gradle:
plugins {
id 'java'
}
group 'dateMWE'
version '1.0-SNAPSHOT'
sourceCompatibility = 10
repositories {
mavenCentral()
}
dependencies {
compile("com.fasterxml.jackson.core:jackson-annotations:2.9.6")
compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.6")
}
The problem is not related with JSON deserialization, but rather with the time format string:
pattern = "yyyy-MM-dd hh:mm:ss"
Please notice that the hours are set as hh: this is a 12-hour formatter, which requires "AM" or "PM" values.
If the pattern is changed to
pattern = "yyyy-MM-dd HH:mm:ss"
the problem should be solved.
Your ObjectMapper is not managed by spring since you are creating object with new. Configure ObjectMapper as Bean in your configuration file. You need to register the DateTimeFormat with your LocalDateTimeDeserializer. Then set your Deserializer in JavaTimeModule.
#Bean
public ObjectMapper objectMapper() {
JavaTimeModule module = new JavaTimeModule();
LocalDateTimeDeserializer localDateTimeDeserializer = new
LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
ObjectMapper objectMapperObj = Jackson2ObjectMapperBuilder.json()
.modules(module)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
return objectMapperObj;
}
Set the above configuration in your Spring configuration.
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?
One solution is to use jackson-modules-java8. Then you can add a JavaTimeModule to your object mapper:
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
objectMapper.registerModule(module);
By default the Instant is serialized as the epoch value (seconds and nanoseconds in a single number):
{"createdDate":1502713067.720000000}
You can change that by setting in the object mapper:
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
This will produce the output:
{"createdDate":"2017-08-14T12:17:47.720Z"}
Both formats above are deserialized without any additional configuration.
To change the serialization format, just add a JsonFormat annotation to the field:
#JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC")
private Instant createdDate;
You need to set the timezone, otherwise the Instant can't be serialized properly (it throws an exception). The output will be:
{"createdDate":"2017-08-14 12:17:47"}
Another alternative, if you don't want to (or can't) use java8 modules, is to create a custom serializer and deserializer, using a java.time.format.DateTimeFormatter:
public class MyCustomSerializer extends JsonSerializer<Instant> {
private DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC);
#Override
public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
String str = fmt.format(value);
gen.writeString(str);
}
}
public class MyCustomDeserializer extends JsonDeserializer<Instant> {
private DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC);
#Override
public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return Instant.from(fmt.parse(p.getText()));
}
}
Then you annotate the field with those custom classes:
#JsonDeserialize(using = MyCustomDeserializer.class)
#JsonSerialize(using = MyCustomSerializer.class)
private Instant createdDate;
The output will be:
{"createdDate":"2017-08-14 12:17:47"}
One detail is that in the serialized string you're discarding the fraction of second (everything after the decimal point). So, when deserializing, this information can't be recovered (it'll be set to zero).
In the example above, the original Instant is 2017-08-14T12:17:47.720Z, but the serialized string is 2017-08-14 12:17:47 (without the fraction of seconds), so when deserialized the resulting Instant is 2017-08-14T12:17:47Z (the .720 milliseconds are lost).
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);
}
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())
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();
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);
You can use Spring ObjectMapper which already configured with JavaTimeModule. Just inject it from Spring context and don't use new ObjectMapper().
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.
I'm using Jackson 2.8 and need to communicate with an API that doesn't allow milliseconds within ISO 8601 timestamps.
The expected format is this: "2016-12-24T00:00:00Z"
I'm using Jackson's JavaTimeModule with WRITE_DATES_AS_TIMESTAMPS set to false.
But this will print milliseconds.
So I tried to use objectMapper.setDateFormat which didn't change anything.
My current workaround is this:
ObjectMapper om = new ObjectMapper();
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendInstant(0)
.toFormatter();
JavaTimeModule jtm = new JavaTimeModule();
jtm.addSerializer(Instant.class, new JsonSerializer<Instant>() {
#Override
public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
gen.writeString(dtf.format(value));
}
});
om.registerModule(jtm);
I'm overriding the default serializer for Instant.class which works.
Is there any nice way using some configuration parameter to solve this?
Update:
Just add a #JsonFormat annotation with the date format above the Instant property. It's very easy.
In the case you have an ObjectMapper with the JavaTimeModule like next:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
If you have a class with an Instant property, you should add the #JsonFormat annotation and put the date pattern which hasn't milliseconds. It would be like next:
public static class TestDate {
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss", timezone = "UTC")
Instant instant;
//getters & setters
}
So if you serialize an object to Json it works perfectly:
String json = mapper.writeValueAsString(testDate);
System.out.println(json);
Output
{"instant":"2016-11-10 06:03:06"}
Old Answer. I don't know why but It doesn't work properly:
You could use the Jackson2ObjectMapperBuilder to build it.
You just need to add the dateFormat you want. It would be something like next:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
ObjectMapper mapper = Jackson2ObjectMapperBuilder
.json()
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.modules(new JavaTimeModule())
.dateFormat(dateFormat)
.build();
Here is an alternative which is something you can set globally, but will need you to use ZonedDateTime with instant formatter as we can't set the format for the Instant Serializer provided with Java Time Module.
You wont see any side effects of using zoned date time for instant as jackson serializes the zone id separately and is disabled by default. So technically, this is similar to applying the formatter to Instant.
When used this way, the ZonedDateTime serializer delegates the serialization to InstantBaseSerializer and uses the specified custom format.
#RunWith(JUnit4.class)
public class InstantNoMillisTest {
private ObjectMapper objectMapper;
#Before
public void init() {
JavaTimeModule module = new JavaTimeModule();
ZonedDateTimeSerializer zonedDateTimeSerializer = new ZonedDateTimeSerializer(new DateTimeFormatterBuilder().appendInstant(0).toFormatter());
module.addSerializer(ZonedDateTime.class, zonedDateTimeSerializer);
module.addDeserializer(ZonedDateTime.class, InstantDeserializer.ZONED_DATE_TIME);
objectMapper = Jackson2ObjectMapperBuilder.json()
.modules(module)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
}
#Test
public void serialize() throws IOException {
ZonedDateTime zonedDateTime = ZonedDateTime.now();
String noMillis = objectMapper.writeValueAsString(zonedDateTime);
System.out.print(noMillis);
}
#Test
public void deserialize() throws IOException {
String dateTime = "\"2017-10-26T12:54:59Z\"";
ZonedDateTime noMillis = objectMapper.readValue(dateTime, ZonedDateTime.class);
System.out.print(noMillis);
}
}
Here's some Kotlin code of formatting Instant fields, so they will 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())
This is my user class, and I to save ISO compliant date time in my database.
public class User {
#Id
private String id;
private String email;
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDateTime loginDate;
}
Here is my Jersey controller:
#POST
#Consumes("application/json")
#Produces("application/json")
public Response create( User user) {
Map<Object, Object> apiResponse = new HashMap<Object, Object>();
Map<Object, Object> response = new HashMap<Object, Object>();
user = (User) userService.create(user);
}
How can can I consume a datetime format like this one in jersey? Is it possible to send a datatime String and create Java 8 date time object automatically?
{
"email" : "imz.mrz#gmail.com"
"loginDate" : "2015-04-17T06:06:51.465Z"
}
#
Update:
I was using Spring boot jersey, and had other jsr packages
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
So I removed all the packages except from spring-boot-jersey package.
use this annotation for LocalDateTime
#JsonDeserialize(using = LocalDateTimeDeserializer.class)
This way I can consume ISODate and save ISODate() to mongodb and produce full formated mongodb LocalDateTime to frontend.
Problem solved.
Couple options I see...
Option 1:
Assuming you have JAXB annotation support with Jackson as the JSON provider...
You could use an XmlAdapter. For example
public class LocalDateTimeAdapter extends XmlAdapter<String, LocalDateTime> {
#Override
public LocalDateTime unmarshal(String dateString) throws Exception {
Instant instant = Instant.parse(dateString);
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
return dateTime;
}
#Override
public String marshal(LocalDateTime dateTime) throws Exception {
Instant instant = dateTime.toInstant(ZoneOffset.UTC);
return DateTimeFormatter.ISO_INSTANT.format(instant);
}
}
See the Instant API for more information.
Then you can just annotate the field/property with the adapter
#XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
private LocalDateTime loginDate;
You could also declare the annotation at the package level, so that all uses in the package will use the adapter, without the need to annotate. You do so in a file named package-info.java put inside the package
#XmlJavaTypeAdapters({
#XmlJavaTypeAdapter(type = LocalDateTime.class,
value = LocalDateTimeAdapter.class)
})
package thepackage.of.the.models;
import java.time.LocalDateTime;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
Option 2:
Use the Jackson APIs directly. Meaning, use a JsonDeserializer and JsonSerializer. For example
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
#Override
public LocalDateTime deserialize(JsonParser jp,
DeserializationContext dc) throws IOException, JsonProcessingException {
ObjectCodec codec = jp.getCodec();
TextNode node = (TextNode)codec.readTree(jp);
String dateString = node.textValue();
Instant instant = Instant.parse(dateString);
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
return dateTime;
}
}
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
#Override
public void serialize(LocalDateTime dateTime, JsonGenerator jg,
SerializerProvider sp) throws IOException, JsonProcessingException {
Instant instant = dateTime.toInstant(ZoneOffset.UTC);
jg.writeString(DateTimeFormatter.ISO_INSTANT.format(instant));
}
}
You can apply this at the field/property level
#JsonSerialize(using = LocalDateTimeSerializer.class)
#JsonDeserialize(using = LocalDateTimeDeserializer.class)
public LocalDateTime loginDate;
Or at the ObjectMapper level (so you don't need to annotate everywhere)
#Provider
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
final ObjectMapper mapper = new ObjectMapper();
public ObjectMapperContextResolver() {
SimpleModule module = new SimpleModule();
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
mapper.registerModule(module);
// add JAXB annotation support if required
mapper.registerModule(new JaxbAnnotationModule());
}
#Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
Basically what happens, is that the MessageBodyWriter/MessageBodyReader used for ummarshalling/marshalling, will call the getContext method to get the ObjectMapper
Note:
The above solutions will parse from the format 2007-12-03T10:15:30.00Z, as documented in Instant.parse, and will serialize to the same format, as documented in DateTimeFormatter.ISO_INSTANT
The above is also assuming you are using Jackson as the Serializer. I used the below dependency (with Jersey 2.16) to test
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.16</version>
</dependency>
The dependency uses a JacksonJaxbJsonProvider for JAXB annotation support. If you are using a lower version of Jersey like 1.x, the jersey-json dependency should offer JAXB annotation support, if you enable the POJO mapping feature. Alternatively for Jersey 1.x, if you want to use Jackson 2, you can use this dependency
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.0</version>
</dependency>
which is actually what is used by jersey-media-json-jackson. So you could explicitly register the JacksonJaxbJsonProvider, or add the Jackson package (com.fasterxml.jackson.jaxrs.json) to list packages to scan
UPDATE
See Also:
Java 8 LocalDate Jackson format. There is Jackson Module that already comes with serializers for the Java 8 date/time APIs.