First, remember to include the JSR-310 module from Jackson, so that he can deal with the classes of java.time
.
Then set the following in ObjectMapper
:
ObjectMapper om = new ObjectMapper();
// adicionar o módulo java.time
JavaTimeModule module = new JavaTimeModule();
om.registerModule(module);
// não converter o timezone
om.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
The option ADJUST_DATES_TO_CONTEXT_TIME_ZONE
should be disabled so that there are no Timezone conversions, and it uses whatever is on ZonedDateTime
.
In the case of Spring, you can also do this via application properties.
And now you have 2 options:
Option 1, use the Serializer
default
Just add these options to ObjectMapper
:
om.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
om.configure(SerializationFeature.WRITE_DATES_WITH_ZONE_ID, true);
And put in your fields:
@JsonProperty("inicio")
private ZonedDateTime start;
@JsonProperty("fim")
private ZonedDateTime stop;
With this, JSON will stay like this:
{
"inicio" : "2019-06-24T20:00:00-03:00[America/Recife]",
"fim" : "2019-06-25T00:00:00-03:00[America/Recife]"
}
Notice that in the hours also the second are placed. But you only wanted "hours:minutes", without the seconds, so in this case you will have to create a Serializer
customized.
Option 2, to use Serializer
customized
In that case you don’t need to change the options WRITE_DATES_AS_TIMESTAMPS
and WRITE_DATES_WITH_ZONE_ID
. Just create a Serializer
customized:
public class CustomZonedDateTimeSerializer extends JsonSerializer<ZonedDateTime> {
private static DateTimeFormatter FMT = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mmXXX'['VV']'");
@Override
public void serialize(ZonedDateTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(FMT.format(value));
}
}
And in the fields, configure them to use this class:
@JsonProperty("inicio")
@JsonSerialize(using = CustomZonedDateTimeSerializer.class)
private ZonedDateTime start;
@JsonProperty("fim")
@JsonSerialize(using = CustomZonedDateTimeSerializer.class)
private ZonedDateTime stop;
With this, JSON will show the hours and minutes, but not the seconds:
{
"inicio" : "2019-06-24T20:00-03:00[America/Recife]",
"fim" : "2019-06-25T00:00-03:00[America/Recife]"
}
Just check if this is really what you need, because when omitting the seconds, whoever is going to receive this JSON will assume that they are zero (usually the API’s, when seeing that the seconds are not present, set the value to zero - the java.time
does that, for example). The same goes for fractions of a second.
Taking advantage, you don’t need to create a Calendar
and then create the ZonedDateTime
.
Like you did calendar.setTime(model.getTempo())
, then I understand that model.getTempo()
returns a java.util.Date
. So just convert it to Instant
and then use atZone
to set the ZoneId
.
Then to change the time, use the method with
passing a java.time.LocalTime
. One detail is that in your code you change the time, minute and second, but the fractions of a second are kept, so you have to remember to keep them when creating the LocalTime
. Would look like this:
ZoneId zoneId = ZoneId.systemDefault();
// converte o Date para ZonedDateTime, usando o ZoneId indicado
ZonedDateTime zdt = model.getTempo().toInstant().atZone(zoneId);
// muda o horário (preservando as frações de segundo)
tempoPojo.setStart(zdt.with(LocalTime.of(10, 30, 30, zdt.getNano())));
// ou, você pode mudar cada campo individualmente
tempoPojo.setStart(zdt.withHour(10).withMinute(30).withSecond(30));
But as said above, if you choose the second option (which does not show the seconds in JSON), then it is useless to set the value of the seconds, because these will be lost when generating JSON (the same goes for the fractions of a second).
My Json remains in the same format, even after the changes... Did not miss my pojo somehow?
– Ananda Lima
@Anandalima Which of the above options have you tried, the 1 or the 2? Note that in each one you have to put Annotations in POJO fields also (
@JsonProperty
and/or@JsonSerialize
). It was the only change I made– hkotsubo
The first option... At first, I only put a Jsonproperty as you suggested, but I believe that only modifies the name of the field in JSON, right? @Jsonserialize would be the second option I haven’t tried yet... OR am I forgetting something in the first one? My pojo looks like this: @Jsonproperty("end") private Zoneddatetime stop;
– Ananda Lima
@Anandalima Good, you have to check if the
ObjectMapper
has been configured correctly with all options, if the java.time module has been added, etc.. 'Cause I tested it here and it worked, maybe it’s one of those missing settings– hkotsubo
The Objectmapper setting I left inside the method that arrow my date (the first part of the explanation + om.configure of the first option). The annotations I put on Pojo were just jsonProperty and I just put the dependency on my pom... Those were all the changes I made... I just think that the settings of the Objectmapper can not stay within the method, apart from that, everything is the same as what you indicated.
– Ananda Lima
Here is everything (variable names and demonstration methods only) https://www.codepile.net/pile/DBvD7dLX
– Ananda Lima
@Anandalima Follow the example I made, only with the changes I mentioned works: https://repl.it/@hkotsubo/Zoneddatetimejsontest#Main.java
– hkotsubo