Bruke valgfritt med Jackson

1. Introduksjon

I denne artikkelen vil vi gi en oversikt over Valgfri klasse, og forklar deretter noen problemer som vi kan støte på når vi bruker den sammen med Jackson.

Etter dette vil vi introdusere en løsning som får Jackson til å behandle Ekstrautstyr som om de var vanlige nullaktive gjenstander.

2. Problemoversikt

La oss først se på hva som skjer når vi prøver å serieisere og deserialisere Ekstrautstyr med Jackson.

2.1. Maven avhengighet

For å bruke Jackson, la oss sørge for at vi bruker den nyeste versjonen:

 com.fasterxml.jackson.core jackson-core 2.11.1 

2.2. Vårt bokobjekt

La oss så lage en klasse Bok, inneholder en vanlig og en Valgfri felt:

public class Book {String title; Valgfri undertittel; // getters og setters utelatt}

Husk det Ekstrautstyr skal ikke brukes som felt, og vi gjør dette for å illustrere problemet.

2.3. Serialisering

La oss nå starte en Bok:

Bokbok = ny bok (); book.setTitle ("Oliver Twist"); book.setSubTitle (Optional.of ("The Parish Boy's Progress"));

Og til slutt, la oss prøve å serieisere det ved hjelp av en Jackson ObjectMapper:

Strengresultat = mapper.writeValueAsString (bok);

Vi får se at utgangen av Valgfri felt, inneholder ikke verdien, men i stedet et nestet JSON-objekt med et felt som heter tilstede:

{"title": "Oliver Twist", "subTitle": {"present": true}}

Selv om dette kan se rart ut, er det faktisk det vi kan forvente.

I dette tilfellet, er tilstede() er en offentlig getter på Valgfri klasse. Dette betyr at den blir seriellisert med verdien ekte eller falsk, avhengig av om den er tom eller ikke. Dette er Jacksons standardiseringsoppførsel.

Hvis vi tenker på det, er det vi ønsker for faktisk verdien av undertekst felt som skal serialiseres.

2.4. Deserialisering

La oss snu vårt forrige eksempel, denne gangen å prøve å deserialisere et objekt til et Valgfri. Vi får se at nå får vi en JsonMappingException:

@Test (forventet = JsonMappingException.class) offentlig ugyldig givenFieldWithValue_whenDeserializing_thenThrowException String bookJson = "{\" title \ ": \" Oliver Twist \ ", \" subTitle \ ": \" foo \ "}"; Bokresultat = mapper.readValue (bookJson, Book.class); } 

La oss se stabelsporet:

com.fasterxml.jackson.databind.JsonMappingException: Kan ikke konstruere forekomst av java.util.Optional: ingen strengargumentkonstruktør / fabrikkmetode for å deserialisere fra strengverdi ('The Parish Boy's Progress')

Denne oppførselen gir igjen mening. I hovedsak trenger Jackson en konstruktør som kan ta verdien av undertekst som argument. Dette er ikke tilfelle med vår Valgfri felt.

3. Løsning

Det vi ønsker, er at Jackson behandler en tom Valgfri som null, og å behandle en gave Valgfri som et felt som representerer verdien.

Heldigvis har dette problemet blitt løst for oss. Jackson har et sett med moduler som omhandler JDK 8 datatyper, inkludert Valgfri.

3.1. Maven avhengighet og registrering

La oss først legge til den nyeste versjonen som en Maven-avhengighet:

 com.fasterxml.jackson.datatype jackson-datatype-jdk8 2.9.6 

Nå er alt vi trenger å gjøre å registrere modulen hos vår ObjectMapper:

ObjectMapper mapper = ny ObjectMapper (); mapper.registerModule (ny Jdk8Module ());

3.2. Serialisering

La oss nå teste det. Hvis vi prøver å serieisere våre Bok motstand igjen, vi får se at det nå er en undertekst, i motsetning til en nestet JSON:

Bokbok = ny bok (); book.setTitle ("Oliver Twist"); book.setSubTitle (Optional.of ("The Parish Boy's Progress")); String serialisertBook = mapper.writeValueAsString (bok); assertThat (fra (serializedBook) .getString ("subTitle")) .isEqualTo ("The Parish Boy's Progress");

Hvis vi prøver å serialisere en tom bok, blir den lagret som null:

book.setSubTitle (Optional.empty ()); String serialisertBook = mapper.writeValueAsString (bok); assertThat (fra (serializedBook) .getString ("undertekst")). er Null ();

3.3. Deserialisering

La oss gjenta testene våre for deserialisering. Hvis vi leser boka vår på nytt, ser vi at vi ikke lenger får en JsonMappingException:

Book newBook ​​= mapper.readValue (resultat, Book.class); assertThat (newBook.getSubTitle ()). isEqualTo (Optional.of ("The Parish Boy's Progress"));

Til slutt, la oss gjenta testen igjen, denne gangen med null. Vi får se at vi igjen ikke får en JsonMappingException, og faktisk ha en tom Valgfri:

assertThat (newBook.getSubTitle ()). isEqualTo (Optional.empty ());

4. Konklusjon

Vi har vist hvordan vi kan komme oss rundt dette problemet ved å utnytte JDK 8 DataTypes-modulen, og demonstrere hvordan det gjør det mulig for Jackson å behandle en tom Valgfri som null, og en gave Valgfri som et vanlig felt.

Implementeringen av disse eksemplene finner du på GitHub; dette er et Maven-basert prosjekt, så det skal være enkelt å kjøre som det er.


$config[zx-auto] not found$config[zx-overlay] not found