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.