Brug valgfri med Jackson

1. Introduktion

I denne artikel giver vi et overblik over Valgfri klasse, og forklar derefter nogle problemer, som vi kan støde på, når vi bruger det sammen med Jackson.

Herefter introducerer vi en løsning, der får Jackson til at behandle Ekstraudstyr som om de var almindelige genstande.

2. Problemoversigt

Lad os først se på, hvad der sker, når vi prøver at serieisere og deserialisere Ekstraudstyr med Jackson.

2.1. Maven afhængighed

For at bruge Jackson, lad os sikre os, at vi bruger den nyeste version:

 com.fasterxml.jackson.core jackson-core 2.11.1 

2.2. Vores bogobjekt

Lad os derefter oprette en klasse Bestil, indeholder en almindelig og en Valgfri Mark:

public class Book {String title; Valgfri undertekst; // getters og setters udeladt}

Husk det Ekstraudstyr bør ikke bruges som felter, og vi gør dette for at illustrere problemet.

2.3. Serialisering

Lad os nu instantiere en Bestil:

Bogbog = ny bog (); book.setTitle ("Oliver Twist"); book.setSubTitle (Optional.of ("Parish Boy's Progress"));

Og endelig, lad os prøve at serieisere det ved hjælp af en Jackson ObjectMapper:

Strengresultat = mapper.writeValueAsString (bog);

Vi ser, at output af Valgfri felt indeholder ikke dens værdi, men i stedet et indlejret JSON-objekt med et felt kaldet til stede:

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

Selvom dette kan se mærkeligt ud, er det faktisk, hvad vi kunne forvente.

I dette tilfælde, er til stede() er en offentlig getter på Valgfri klasse. Dette betyder, at den serieliseres med en værdi på rigtigt eller falskafhængigt af om den er tom eller ej. Dette er Jacksons standardserieringsadfærd.

Hvis vi tænker over det, er det, vi ønsker, faktisk værdi af undertekst felt, der skal serialiseres.

2.4. Deserialisering

Lad os nu vende vores tidligere eksempel, denne gang forsøger vi at deserialisere et objekt til et Valgfri. Vi ser, at nu får vi en JsonMappingException:

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

Lad os se stacksporingen:

com.fasterxml.jackson.databind.JsonMappingException: Kan ikke konstruere forekomst af java.util.Optional: ingen strengargumentkonstruktør / fabriksmetode til at deserialisere fra strengværdi ('The Parish Boy's Progress')

Denne opførsel giver igen mening. I det væsentlige har Jackson brug for en konstruktør, der kan tage værdien af undertekst som et argument. Dette er ikke tilfældet med vores Valgfri Mark.

3. Løsning

Hvad vi ønsker, er, at Jackson behandler en tom Valgfri som nul, og at behandle en gave Valgfri som et felt, der repræsenterer dets værdi.

Heldigvis er dette problem løst for os. Jackson har et sæt moduler, der beskæftiger sig med JDK 8 datatyper, inklusive Valgfri.

3.1. Maven afhængighed og registrering

Lad os først tilføje den nyeste version som en Maven-afhængighed:

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

Nu er alt, hvad vi skal gøre, at registrere modulet med vores ObjectMapper:

ObjectMapper-kortlægger = ny ObjectMapper (); mapper.registerModule (ny Jdk8Module ());

3.2. Serialisering

Lad os nu teste det. Hvis vi prøver at serieisere vores Bestil modstand igen, vi ser, at der nu er en undertekst, i modsætning til en indlejret JSON:

Bogbog = ny bog (); book.setTitle ("Oliver Twist"); book.setSubTitle (Optional.of ("Parish Boy's Progress")); String serializedBook = mapper.writeValueAsString (bog); assertThat (fra (serializedBook) .getString ("undertekst")) .isEqualTo ("Parish Boy's Progress");

Hvis vi prøver at serialisere en tom bog, gemmes den som nul:

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

3.3. Deserialisering

Lad os nu gentage vores tests til deserialisering. Hvis vi læser vores bog igen, ser vi, at vi ikke længere får en JsonMappingException:

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

Lad os endelig gentage testen igen, denne gang med nul. Vi ser, at vi endnu en gang ikke får en JsonMappingException, og faktisk have en tom Valgfri:

assertThat (newBook.getSubTitle ()). er EqualTo (Optional.empty ());

4. Konklusion

Vi har vist, hvordan vi kan omgå dette problem ved at udnytte JDK 8 DataTypes-modulet og demonstrere, hvordan det gør det muligt for Jackson at behandle en tom Valgfri som nul, og en gave Valgfri som et almindeligt felt.

Implementeringen af ​​disse eksempler findes på GitHub; dette er et Maven-baseret projekt, så det skal være let at køre som det er.


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