Skip to content

Commit 4cb5407

Browse files
authored
Legger til CustomZonedDateTimeDeSerializer for håndtering av ZDT. (#458)
* 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.
1 parent 1290365 commit 4cb5407

File tree

5 files changed

+114
-60
lines changed

5 files changed

+114
-60
lines changed

ettersendelse/src/main/java/no/nav/k9/ettersendelse/Ettersendelse.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,19 @@
11
package no.nav.k9.ettersendelse;
22

3-
import java.io.IOException;
4-
import java.time.ZonedDateTime;
5-
3+
import com.fasterxml.jackson.annotation.*;
4+
import com.fasterxml.jackson.databind.node.ObjectNode;
65
import jakarta.validation.Valid;
76
import jakarta.validation.constraints.NotNull;
8-
9-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
10-
import com.fasterxml.jackson.annotation.JsonCreator;
11-
import com.fasterxml.jackson.annotation.JsonFormat;
12-
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
13-
import com.fasterxml.jackson.annotation.JsonProperty;
14-
import com.fasterxml.jackson.databind.node.ObjectNode;
15-
167
import no.nav.k9.søknad.Innsending;
178
import no.nav.k9.søknad.JsonUtils;
9+
import no.nav.k9.søknad.felles.DtoKonstanter;
1810
import no.nav.k9.søknad.felles.Versjon;
1911
import no.nav.k9.søknad.felles.personopplysninger.Søker;
2012
import no.nav.k9.søknad.felles.type.SøknadId;
2113

14+
import java.io.IOException;
15+
import java.time.ZonedDateTime;
16+
2217
@JsonIgnoreProperties(ignoreUnknown = true)
2318
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE)
2419
public class Ettersendelse implements Innsending {
@@ -34,7 +29,7 @@ public class Ettersendelse implements Innsending {
3429

3530
@JsonProperty(value="mottattDato")
3631
@Valid
37-
@JsonFormat(shape = JsonFormat.Shape.STRING, timezone = "UTC")
32+
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DtoKonstanter.DATO_TID_FORMAT, timezone = DtoKonstanter.TIDSSONE)
3833
private final ZonedDateTime mottattDato;
3934

4035
@JsonProperty(value="søker", required = true)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package no.nav.k9.søknad;
2+
3+
import com.fasterxml.jackson.core.JsonParser;
4+
import com.fasterxml.jackson.core.JsonProcessingException;
5+
import com.fasterxml.jackson.databind.DeserializationContext;
6+
import com.fasterxml.jackson.databind.JsonDeserializer;
7+
8+
import java.io.IOException;
9+
import java.time.ZonedDateTime;
10+
import java.time.format.DateTimeFormatter;
11+
import java.time.format.DateTimeFormatterBuilder;
12+
import java.time.temporal.ChronoField;
13+
14+
public class CustomZonedDateTimeDeSerializer extends JsonDeserializer<ZonedDateTime> {
15+
16+
static final DateTimeFormatter zonedDateTimeFormatter = new DateTimeFormatterBuilder()
17+
// 2024-08-14T10:05:56
18+
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
19+
.optionalStart()
20+
// 2024-08-14T10:05:56.111
21+
.appendFraction(ChronoField.MILLI_OF_SECOND, 0, 9, true)
22+
.optionalEnd()
23+
// 2024-08-14T10:05:56.111+02:00
24+
.appendPattern("ZZZZZ")
25+
.optionalStart()
26+
// 2024-08-14T10:05:56.111+02:00[Europe/Oslo]
27+
.appendLiteral('[')
28+
.appendZoneRegionId()
29+
.appendLiteral(']')
30+
.optionalEnd()
31+
.toFormatter();
32+
33+
@Override
34+
public ZonedDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
35+
String value = p.getValueAsString();
36+
return ZonedDateTime.parse(value, zonedDateTimeFormatter);
37+
}
38+
}

soknad/src/main/java/no/nav/k9/søknad/JsonUtils.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
package no.nav.k9.søknad;
22

3-
import java.io.IOException;
4-
import java.util.TimeZone;
5-
63
import com.fasterxml.jackson.core.JsonGenerator;
74
import com.fasterxml.jackson.core.JsonProcessingException;
85
import com.fasterxml.jackson.core.util.DefaultIndenter;
96
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
10-
import com.fasterxml.jackson.databind.DeserializationFeature;
11-
import com.fasterxml.jackson.databind.MapperFeature;
12-
import com.fasterxml.jackson.databind.ObjectMapper;
13-
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
14-
import com.fasterxml.jackson.databind.SerializationFeature;
7+
import com.fasterxml.jackson.databind.*;
158
import com.fasterxml.jackson.databind.node.ObjectNode;
169
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
1710
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
18-
11+
import no.nav.k9.søknad.felles.DtoKonstanter;
1912
import no.nav.k9.søknad.ytelse.omsorgspenger.v1.OmsorgspengerUtbetaling;
2013
import no.nav.k9.søknad.ytelse.psb.v1.PleiepengerSyktBarn;
2114

15+
import java.io.IOException;
16+
import java.text.SimpleDateFormat;
17+
import java.time.ZonedDateTime;
18+
import java.util.TimeZone;
19+
2220
public final class JsonUtils {
2321

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

6159
private static final ObjectMapper createObjectMapper() {
60+
JavaTimeModule javaTimeModule = new JavaTimeModule();
61+
javaTimeModule.addDeserializer(ZonedDateTime.class, new CustomZonedDateTimeDeSerializer());
62+
63+
6264
final ObjectMapper objectMapper = new ObjectMapper()
6365
.registerModule(new Jdk8Module())
64-
.registerModule(new JavaTimeModule())
66+
.registerModule(javaTimeModule)
6567
.setPropertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE)
6668
.setTimeZone(TimeZone.getTimeZone("UTC"))
6769
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
@@ -74,6 +76,7 @@ private static final ObjectMapper createObjectMapper() {
7476
.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
7577

7678
objectMapper.registerSubtypes(OmsorgspengerUtbetaling.class, PleiepengerSyktBarn.class);
79+
objectMapper.setDateFormat(new SimpleDateFormat(DtoKonstanter.DATO_TID_FORMAT));
7780

7881
return objectMapper;
7982
}

soknad/src/main/java/no/nav/k9/søknad/Søknad.java

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,21 @@
11
package no.nav.k9.søknad;
22

3-
import java.io.IOException;
4-
import java.time.ZonedDateTime;
5-
import java.util.ArrayList;
6-
import java.util.Collections;
7-
import java.util.List;
8-
import java.util.Objects;
9-
import java.util.Optional;
10-
11-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
12-
import com.fasterxml.jackson.annotation.JsonCreator;
13-
import com.fasterxml.jackson.annotation.JsonFormat;
14-
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
15-
import com.fasterxml.jackson.annotation.JsonManagedReference;
16-
import com.fasterxml.jackson.annotation.JsonProperty;
3+
import com.fasterxml.jackson.annotation.*;
174
import com.fasterxml.jackson.databind.node.ObjectNode;
18-
195
import jakarta.validation.Valid;
206
import jakarta.validation.constraints.NotNull;
217
import jakarta.validation.constraints.Size;
228
import no.nav.k9.søknad.felles.DtoKonstanter;
239
import no.nav.k9.søknad.felles.Kildesystem;
2410
import no.nav.k9.søknad.felles.Versjon;
2511
import no.nav.k9.søknad.felles.personopplysninger.Søker;
26-
import no.nav.k9.søknad.felles.type.BegrunnelseForInnsending;
27-
import no.nav.k9.søknad.felles.type.Journalpost;
28-
import no.nav.k9.søknad.felles.type.Person;
29-
import no.nav.k9.søknad.felles.type.Språk;
30-
import no.nav.k9.søknad.felles.type.SøknadId;
12+
import no.nav.k9.søknad.felles.type.*;
3113
import no.nav.k9.søknad.ytelse.Ytelse;
3214

15+
import java.io.IOException;
16+
import java.time.ZonedDateTime;
17+
import java.util.*;
18+
3319
@JsonIgnoreProperties(ignoreUnknown = true)
3420
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE)
3521
public class Søknad implements Innsending {
@@ -46,7 +32,8 @@ public class Søknad implements Innsending {
4632

4733
@Valid
4834
@NotNull
49-
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DtoKonstanter.DATO_TID_FORMAT, timezone = DtoKonstanter.TIDSSONE) @JsonProperty(value = "mottattDato", required = true)
35+
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DtoKonstanter.DATO_TID_FORMAT, timezone = DtoKonstanter.TIDSSONE)
36+
@JsonProperty(value = "mottattDato", required = true)
5037
private ZonedDateTime mottattDato;
5138

5239
@Valid
@@ -72,7 +59,7 @@ public class Søknad implements Innsending {
7259
@NotNull
7360
@JsonProperty(value = "ytelse", required = true)
7461
private Ytelse ytelse;
75-
62+
7663
@Valid
7764
@JsonProperty(value = "kildesystem", required = false)
7865
private Kildesystem kildesystem;
@@ -144,14 +131,14 @@ public List<Journalpost> getJournalposter() {
144131
public <Y extends Ytelse> Y getYtelse() {
145132
return (Y) ytelse;
146133
}
147-
134+
148135
/**
149136
* Dette feltet kan brukes til å oppgi kildesystem. For historiske data
150137
* er feltet kun garantert å være satt for alle søknader som kommer fra
151138
* endringsdialogen. Ved behov for å se på historiske data av andre typer,
152139
* se på journalpostens kanalfelt og/eller metadatafeltet på journalposten
153-
* kalt "k9.kilde".
154-
*
140+
* kalt "k9.kilde".
141+
*
155142
* @return Systemet som søknadsdataene kommer fra.
156143
*/
157144
public Optional<Kildesystem> getKildesystem() {
@@ -177,7 +164,7 @@ public void setMottattDato(ZonedDateTime mottattDato) {
177164
public void setYtelse(Ytelse ytelse) {
178165
this.ytelse = Objects.requireNonNull(ytelse, "ytelse");
179166
}
180-
167+
181168
public void setKildesystem(Kildesystem kildesystem) {
182169
this.kildesystem = kildesystem;
183170
}
@@ -236,7 +223,7 @@ public void setKildesystem(Kildesystem kildesystem) {
236223
this.journalposter.addAll(Objects.requireNonNull(journalposter, "journalposter"));
237224
return this;
238225
}
239-
226+
240227
/**
241228
* @see #getKildesystem()
242229
*/

soknad/src/test/java/no/nav/k9/søknad/JsonUtilsTest.java

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
package no.nav.k9.søknad;
22

3-
import static org.assertj.core.api.Assertions.assertThat;
4-
5-
import java.time.ZonedDateTime;
6-
3+
import com.fasterxml.jackson.databind.node.ObjectNode;
74
import org.assertj.core.api.Assertions;
85
import org.junit.jupiter.api.Test;
96
import org.junit.jupiter.params.ParameterizedTest;
107
import org.junit.jupiter.params.provider.ValueSource;
118

12-
import com.fasterxml.jackson.databind.node.ObjectNode;
9+
import java.time.ZonedDateTime;
10+
import java.time.format.DateTimeParseException;
11+
12+
import static org.assertj.core.api.Assertions.assertThat;
13+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
14+
import static org.assertj.core.api.AssertionsForClassTypes.assertThatNoException;
1315

1416
public class JsonUtilsTest {
1517

1618
@Test
1719
public void reserialiseringSkalAlltidGiSammeJson() {
18-
final String testdataverdi = "foobar" ;
20+
final String testdataverdi = "foobar";
1921

2022
final Testdata testdata = new Testdata();
2123
testdata.setFelt(testdataverdi);
@@ -35,8 +37,8 @@ public void ukjentePropertiesSkalGiException() {
3537
final Testdata testdata = new Testdata();
3638
final ObjectNode objectNode = JsonUtils.toObjectNode(testdata);
3739

38-
final String feltnavn = "nyttFeltnavn" ;
39-
final String feltverdi = "nyFeltverdi" ;
40+
final String feltnavn = "nyttFeltnavn";
41+
final String feltverdi = "nyFeltverdi";
4042
objectNode.put(feltnavn, feltverdi);
4143

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

5557
@ParameterizedTest
5658
@ValueSource(strings = {
57-
"\"2024-08-14T10:05:56.111111111Z\"",
5859
"\"2024-08-14T10:05:56.111111Z\"",
5960
"\"2024-08-14T10:05:56.111Z\"",
60-
"\"2024-08-14T10:05:56Z\""})
61+
"\"2024-08-14T10:05:56Z\""
62+
})
6163
public void skal_kunne_deserialisere_zoneddatetime(String dato) {
62-
deserialiserZonedDatetime(dato);
64+
Assertions.assertThatNoException().isThrownBy(() -> deserialiserZonedDatetime(dato));
65+
}
66+
67+
@ParameterizedTest
68+
@ValueSource(strings = {
69+
"2024-08-14T10:05:56.111111111Z",
70+
"2024-08-14T10:05:56.11111111Z",
71+
"2024-08-14T10:05:56.1111111Z",
72+
"2024-08-14T10:05:56.111111Z",
73+
"2024-08-14T10:05:56.11111Z",
74+
"2024-08-14T10:05:56.1111Z",
75+
"2024-08-14T10:05:56.111Z",
76+
"2024-08-14T10:05:56.11Z",
77+
"2024-08-14T10:05:56.1Z",
78+
"2024-08-14T10:05:56Z",
79+
"2024-08-14T10:05:56.111+02:00",
80+
"2024-08-14T10:05:56.111+02:00[Europe/Oslo]",
81+
})
82+
public void deserialisering_av_zdt_skal_ikke_feile(String dato) {
83+
assertThatNoException().isThrownBy(() -> ZonedDateTime.parse(dato, CustomZonedDateTimeDeSerializer.zonedDateTimeFormatter));
84+
}
85+
86+
@ParameterizedTest
87+
@ValueSource(strings = {
88+
"2024-08-14T10:05:56.1111111111Z",
89+
"2024-08-14T10:05Z"
90+
})
91+
public void deserialisering_av_zdt_skal_feile(String dato) {
92+
assertThatThrownBy(() -> ZonedDateTime.parse(dato, CustomZonedDateTimeDeSerializer.zonedDateTimeFormatter))
93+
.isInstanceOf(DateTimeParseException.class);
6394
}
6495

6596
private static ZonedDateTime deserialiserZonedDatetime(String s) {

0 commit comments

Comments
 (0)