Korištenje Neobvezno s Jacksonom

1. Uvod

U ovom ćemo članku dati pregled Neobvezno razredu, a zatim objasnite neke probleme na koje bismo mogli naletjeti kada ga koristimo s Jacksonom.

Nakon toga predstavit ćemo rješenje kojim ćemo Jacksona liječiti Opcionalni kao da su to obični poništivi predmeti.

2. Pregled problema

Prvo, pogledajmo što se događa kada pokušavamo serializirati i deserializirati Opcionalni s Jacksonom.

2.1. Ovisnost Mavena

Da bismo koristili Jacksona, pobrinimo se da koristimo njegovu najnoviju verziju:

 com.fasterxml.jackson.core jackson-core 2.11.1 

2.2. Naš objekt knjige

Zatim, kreirajmo razred Knjiga, koji sadrži jedan običan i jedan Neobvezno polje:

public class Book {Naslov niza; Izborni podnaslov; // izostavljeni geteri i postavljači}

Imajte na umu da Opcionalni ne bi se trebali koristiti kao polja i to radimo da bismo ilustrirali problem.

2.3. Serijalizacija

Sada, napravimo instancu a Knjiga:

Knjiga knjiga = nova Knjiga (); book.setTitle ("Oliver Twist"); book.setSubTitle (po izboru.of ("Napredak dječaka iz župe"));

I na kraju, pokušajmo ga serializirati pomoću Jacksona ObjectMapper:

Rezultat niza = mapper.writeValueAsString (knjiga);

Vidjet ćemo da je izlaz Neobvezno polje ne sadrži njegovu vrijednost, već umjesto toga ugniježđeni JSON objekt s poljem pozvanim predstaviti:

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

Iako ovo može izgledati čudno, zapravo je ono što bismo trebali očekivati.

U ovom slučaju, je prisutan() je javni nabavljač na Neobvezno razred. To znači da će biti serializirana s vrijednošću pravi ili lažno, ovisno o tome je li prazan ili ne. Ovo je Jacksonovo zadano ponašanje u serializaciji.

Ako razmislimo o tome, ono što želimo je stvarna vrijednost titl polje za serializaciju.

2.4. Deserijalizacija

Sada, vratimo obrnuti naš prethodni primjer, ovaj put pokušavajući deserializirati objekt u Neobvezno. Vidjet ćemo da ćemo sada dobiti JsonMappingException:

@Test (očekuje se = JsonMappingException.class) javna praznina givenFieldWithValue_whenDeserializing_thenThrowException String bookJson = "{\" title \ ": \" Oliver Twist \ ", \" subTitle \ ": \" foo \ "}"; Rezultat knjige = mapper.readValue (bookJson, Book.class); } 

Pogledajmo trag steka:

com.fasterxml.jackson.databind.JsonMappingException: Ne može se konstruirati instanca java.util.Obavezno: nema konstruktorskog argumenta niza / tvorničke metode za deserializaciju iz vrijednosti niza ('Napredak dječaka iz župe')

Ovo ponašanje opet ima smisla. U osnovi, Jacksonu treba konstruktor koji može uzeti vrijednost titl kao argument. To nije slučaj s našim Neobvezno polje.

3. Rješenje

Ono što želimo je da Jackson postupa s prazninom Neobvezno kao null, i za liječenje poklona Neobvezno kao polje koje predstavlja njegovu vrijednost.

Srećom, ovaj je problem za nas riješen. Jackson ima skup modula koji se bave JDK 8 tipovima podataka, uključujući Neobvezno.

3.1. Ovisnost i registracija Mavena

Prvo, dodajmo najnoviju verziju kao ovisnost o Mavenu:

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

Sada sve što trebamo jest registrirati modul na našem ObjectMapper:

Mapa ObjectMapper = novi ObjectMapper (); mapper.registerModule (novi Jdk8Module ());

3.2. Serijalizacija

Ajmo sad, testirajmo. Ako pokušamo i serializiramo svoje Knjiga objekt opet, vidjet ćemo da sada postoji titl, za razliku od ugniježđenog JSON-a:

Knjiga knjiga = nova Knjiga (); book.setTitle ("Oliver Twist"); book.setSubTitle (po izboru.of ("Napredak dječaka iz župe")); Niz serializedBook = mapper.writeValueAsString (knjiga); assertThat (iz (serializedBook) .getString ("podnaslov")) .isEqualTo ("Napredak dječaka iz župe");

Ako pokušamo serializirati praznu knjigu, ona će biti pohranjena kao null:

book.setSubTitle (Izborno.prazno ()); Niz serializedBook = mapper.writeValueAsString (knjiga); assertThat (iz (serializedBook) .getString ("podnaslov")). isNull ();

3.3. Deserijalizacija

Ponovimo sada naše testove za deserializaciju. Ako ponovno čitamo našu Knjigu, vidjet ćemo da više ne dobivamo a JsonMappingException:

Book newBook ​​= mapper.readValue (rezultat, Book.class); assertThat (newBook.getSubTitle ()). isEqualTo (Neobvezno.of ("Napredak dječaka iz župe"));

Napokon, ponovimo test ponovo, ovaj put sa null. Vidjet ćemo da još jednom nećemo dobiti JsonMappingException, i zapravo, imaju prazan Neobvezno:

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

4. Zaključak

Pokazali smo kako zaobići ovaj problem iskorištavanjem modula JDK 8 DataTypes, demonstrirajući kako omogućava Jacksonu da tretira prazno Neobvezno kao null, i poklon Neobvezno kao obično polje.

Implementacija ovih primjera može se naći na GitHub-u; ovo je projekt zasnovan na Mavenu, pa bi ga trebalo biti lako pokrenuti kakav jest.


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