Skip to content

Commit

Permalink
Legger til CustomZonedDateTimeDeSerializer for håndtering av ZDT. (#458)
Browse files Browse the repository at this point in the history
* Legger til CustomZonedDateTimeDeSerializer for håndtering ZDT.

CustomZonedDateTimeDeSerializer støtter deserialisering av zdt uten og med ms fra 0-6 siffer.
ZDT uten sekund del skal fortsatt feile.

* Legger til CustomZonedDateTimeDeSerializer for håndtering ZDT.

CustomZonedDateTimeDeSerializer støtter deserialisering av zdt uten og med ms fra 0-6 siffer.
ZDT uten sekund del skal fortsatt feile.

* Erstatter NANO_OF_SECOND med MILLI_OF_SECOND.

* Støtter offset (+01:00)

* Støtter region id.
  • Loading branch information
ramrock93 authored Aug 16, 2024
1 parent 1290365 commit 4cb5407
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
package no.nav.k9.ettersendelse;

import java.io.IOException;
import java.time.ZonedDateTime;

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.node.ObjectNode;

import no.nav.k9.søknad.Innsending;
import no.nav.k9.søknad.JsonUtils;
import no.nav.k9.søknad.felles.DtoKonstanter;
import no.nav.k9.søknad.felles.Versjon;
import no.nav.k9.søknad.felles.personopplysninger.Søker;
import no.nav.k9.søknad.felles.type.SøknadId;

import java.io.IOException;
import java.time.ZonedDateTime;

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE)
public class Ettersendelse implements Innsending {
Expand All @@ -34,7 +29,7 @@ public class Ettersendelse implements Innsending {

@JsonProperty(value="mottattDato")
@Valid
@JsonFormat(shape = JsonFormat.Shape.STRING, timezone = "UTC")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DtoKonstanter.DATO_TID_FORMAT, timezone = DtoKonstanter.TIDSSONE)
private final ZonedDateTime mottattDato;

@JsonProperty(value="søker", required = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package no.nav.k9.søknad;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

import java.io.IOException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;

public class CustomZonedDateTimeDeSerializer extends JsonDeserializer<ZonedDateTime> {

static final DateTimeFormatter zonedDateTimeFormatter = new DateTimeFormatterBuilder()
// 2024-08-14T10:05:56
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
.optionalStart()
// 2024-08-14T10:05:56.111
.appendFraction(ChronoField.MILLI_OF_SECOND, 0, 9, true)
.optionalEnd()
// 2024-08-14T10:05:56.111+02:00
.appendPattern("ZZZZZ")
.optionalStart()
// 2024-08-14T10:05:56.111+02:00[Europe/Oslo]
.appendLiteral('[')
.appendZoneRegionId()
.appendLiteral(']')
.optionalEnd()
.toFormatter();

@Override
public ZonedDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String value = p.getValueAsString();
return ZonedDateTime.parse(value, zonedDateTimeFormatter);
}
}
23 changes: 13 additions & 10 deletions soknad/src/main/java/no/nav/k9/søknad/JsonUtils.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
package no.nav.k9.søknad;

import java.io.IOException;
import java.util.TimeZone;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import no.nav.k9.søknad.felles.DtoKonstanter;
import no.nav.k9.søknad.ytelse.omsorgspenger.v1.OmsorgspengerUtbetaling;
import no.nav.k9.søknad.ytelse.psb.v1.PleiepengerSyktBarn;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.ZonedDateTime;
import java.util.TimeZone;

public final class JsonUtils {

private static final ObjectMapper objectMapper = createObjectMapper();
Expand Down Expand Up @@ -59,9 +57,13 @@ static ObjectNode toObjectNode(Object object) {
}

private static final ObjectMapper createObjectMapper() {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(ZonedDateTime.class, new CustomZonedDateTimeDeSerializer());


final ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule())
.registerModule(javaTimeModule)
.setPropertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE)
.setTimeZone(TimeZone.getTimeZone("UTC"))
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
Expand All @@ -74,6 +76,7 @@ private static final ObjectMapper createObjectMapper() {
.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);

objectMapper.registerSubtypes(OmsorgspengerUtbetaling.class, PleiepengerSyktBarn.class);
objectMapper.setDateFormat(new SimpleDateFormat(DtoKonstanter.DATO_TID_FORMAT));

return objectMapper;
}
Expand Down
41 changes: 14 additions & 27 deletions soknad/src/main/java/no/nav/k9/søknad/Søknad.java
Original file line number Diff line number Diff line change
@@ -1,35 +1,21 @@
package no.nav.k9.søknad;

import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.node.ObjectNode;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import no.nav.k9.søknad.felles.DtoKonstanter;
import no.nav.k9.søknad.felles.Kildesystem;
import no.nav.k9.søknad.felles.Versjon;
import no.nav.k9.søknad.felles.personopplysninger.Søker;
import no.nav.k9.søknad.felles.type.BegrunnelseForInnsending;
import no.nav.k9.søknad.felles.type.Journalpost;
import no.nav.k9.søknad.felles.type.Person;
import no.nav.k9.søknad.felles.type.Språk;
import no.nav.k9.søknad.felles.type.SøknadId;
import no.nav.k9.søknad.felles.type.*;
import no.nav.k9.søknad.ytelse.Ytelse;

import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.*;

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE)
public class Søknad implements Innsending {
Expand All @@ -46,7 +32,8 @@ public class Søknad implements Innsending {

@Valid
@NotNull
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DtoKonstanter.DATO_TID_FORMAT, timezone = DtoKonstanter.TIDSSONE) @JsonProperty(value = "mottattDato", required = true)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DtoKonstanter.DATO_TID_FORMAT, timezone = DtoKonstanter.TIDSSONE)
@JsonProperty(value = "mottattDato", required = true)
private ZonedDateTime mottattDato;

@Valid
Expand All @@ -72,7 +59,7 @@ public class Søknad implements Innsending {
@NotNull
@JsonProperty(value = "ytelse", required = true)
private Ytelse ytelse;

@Valid
@JsonProperty(value = "kildesystem", required = false)
private Kildesystem kildesystem;
Expand Down Expand Up @@ -144,14 +131,14 @@ public List<Journalpost> getJournalposter() {
public <Y extends Ytelse> Y getYtelse() {
return (Y) ytelse;
}

/**
* Dette feltet kan brukes til å oppgi kildesystem. For historiske data
* er feltet kun garantert å være satt for alle søknader som kommer fra
* endringsdialogen. Ved behov for å se på historiske data av andre typer,
* se på journalpostens kanalfelt og/eller metadatafeltet på journalposten
* kalt "k9.kilde".
*
* kalt "k9.kilde".
*
* @return Systemet som søknadsdataene kommer fra.
*/
public Optional<Kildesystem> getKildesystem() {
Expand All @@ -177,7 +164,7 @@ public void setMottattDato(ZonedDateTime mottattDato) {
public void setYtelse(Ytelse ytelse) {
this.ytelse = Objects.requireNonNull(ytelse, "ytelse");
}

public void setKildesystem(Kildesystem kildesystem) {
this.kildesystem = kildesystem;
}
Expand Down Expand Up @@ -236,7 +223,7 @@ public void setKildesystem(Kildesystem kildesystem) {
this.journalposter.addAll(Objects.requireNonNull(journalposter, "journalposter"));
return this;
}

/**
* @see #getKildesystem()
*/
Expand Down
53 changes: 42 additions & 11 deletions soknad/src/test/java/no/nav/k9/søknad/JsonUtilsTest.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
package no.nav.k9.søknad;

import static org.assertj.core.api.Assertions.assertThat;

import java.time.ZonedDateTime;

import com.fasterxml.jackson.databind.node.ObjectNode;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import com.fasterxml.jackson.databind.node.ObjectNode;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatNoException;

public class JsonUtilsTest {

@Test
public void reserialiseringSkalAlltidGiSammeJson() {
final String testdataverdi = "foobar" ;
final String testdataverdi = "foobar";

final Testdata testdata = new Testdata();
testdata.setFelt(testdataverdi);
Expand All @@ -35,8 +37,8 @@ public void ukjentePropertiesSkalGiException() {
final Testdata testdata = new Testdata();
final ObjectNode objectNode = JsonUtils.toObjectNode(testdata);

final String feltnavn = "nyttFeltnavn" ;
final String feltverdi = "nyFeltverdi" ;
final String feltnavn = "nyttFeltnavn";
final String feltverdi = "nyFeltverdi";
objectNode.put(feltnavn, feltverdi);

final String json = JsonUtils.toString(objectNode);
Expand All @@ -54,12 +56,41 @@ public void ukjentePropertiesSkalGiException() {

@ParameterizedTest
@ValueSource(strings = {
"\"2024-08-14T10:05:56.111111111Z\"",
"\"2024-08-14T10:05:56.111111Z\"",
"\"2024-08-14T10:05:56.111Z\"",
"\"2024-08-14T10:05:56Z\""})
"\"2024-08-14T10:05:56Z\""
})
public void skal_kunne_deserialisere_zoneddatetime(String dato) {
deserialiserZonedDatetime(dato);
Assertions.assertThatNoException().isThrownBy(() -> deserialiserZonedDatetime(dato));
}

@ParameterizedTest
@ValueSource(strings = {
"2024-08-14T10:05:56.111111111Z",
"2024-08-14T10:05:56.11111111Z",
"2024-08-14T10:05:56.1111111Z",
"2024-08-14T10:05:56.111111Z",
"2024-08-14T10:05:56.11111Z",
"2024-08-14T10:05:56.1111Z",
"2024-08-14T10:05:56.111Z",
"2024-08-14T10:05:56.11Z",
"2024-08-14T10:05:56.1Z",
"2024-08-14T10:05:56Z",
"2024-08-14T10:05:56.111+02:00",
"2024-08-14T10:05:56.111+02:00[Europe/Oslo]",
})
public void deserialisering_av_zdt_skal_ikke_feile(String dato) {
assertThatNoException().isThrownBy(() -> ZonedDateTime.parse(dato, CustomZonedDateTimeDeSerializer.zonedDateTimeFormatter));
}

@ParameterizedTest
@ValueSource(strings = {
"2024-08-14T10:05:56.1111111111Z",
"2024-08-14T10:05Z"
})
public void deserialisering_av_zdt_skal_feile(String dato) {
assertThatThrownBy(() -> ZonedDateTime.parse(dato, CustomZonedDateTimeDeSerializer.zonedDateTimeFormatter))
.isInstanceOf(DateTimeParseException.class);
}

private static ZonedDateTime deserialiserZonedDatetime(String s) {
Expand Down

0 comments on commit 4cb5407

Please sign in to comment.