Az Opcionális használata Jacksonnal

1. Bemutatkozás

Ebben a cikkben áttekintést adunk a Választható osztályban, majd magyarázzon el néhány problémát, amelyekbe belefuthatunk, ha Jacksonnal használjuk.

Ezt követően bemutatunk egy megoldást, amely Jackson kezelésére készteti Opcionális mintha közönséges semmissé váló tárgyak lennének.

2. A probléma áttekintése

Először vessünk egy pillantást arra, hogy mi történik, amikor megpróbáljuk sorosítani és deszerializálni Opcionális Jacksonnal.

2.1. Maven-függőség

Jackson használatához győződjön meg arról, hogy a legújabb verzióját használjuk:

 com.fasterxml.jackson.core jackson-core 2.11.1 

2.2. Könyvtárgyunk

Ezután hozzunk létre egy osztályt Könyv, egy közönséget és egyet Választható terület:

nyilvános osztály Könyv {Húr cím; Opcionális alcím; // getterek és beállítók kihagyva}

Tartsd észben, hogy Opcionális nem szabad mezőként használni, és ezt a probléma szemléltetésére tesszük.

2.3. Serializálás

Most példázzuk a Könyv:

Könyvkönyv = új Könyv (); book.setTitle ("Oliver Twist"); book.setSubTitle (Opcionális.of ("A plébános fiú haladása"));

És végül próbáljuk meg egy Jackson használatával sorosítani ObjectMapper:

Karakterlánc eredménye = mapper.writeValueAsString (könyv);

Meglátjuk, hogy a Választható mező nem tartalmazza az értékét, hanem egy beágyazott JSON objektumot, amelynek neve mező ajándék:

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

Bár ez furcsának tűnhet, valójában erre kell számítanunk.

Ebben az esetben, jelen van() nyilvános ismeretterjesztő a Választható osztály. Ez azt jelenti, hogy soros lesz, amelynek értéke: igaz vagy hamis, attól függően, hogy üres-e vagy sem. Ez Jackson alapértelmezett sorosítási viselkedése.

Ha belegondolunk, amit akarunk, az a tényleges értéke felirat sorosítandó mező.

2.4. Deserializáció

Most fordítsuk meg előző példánkat, ezúttal megpróbálva deserializálni egy objektumot Választható. Meglátjuk, hogy most kapunk egy JsonMappingException:

@Test (várható = JsonMappingException.class) public void givenFieldWithValue_whenDeserializing_thenThrowException String bookJson = "{\" title \ ": \" Oliver Twist \ ", \" subTitle \ ": \" foo \ "}"; Könyv eredménye = mapper.readValue (bookJson, Book.class); } 

Nézzük meg a verem nyomát:

com.fasterxml.jackson.databind.JsonMappingException: Nem lehet elkészíteni a java.util példányát. Opcionális: nincs String argumentumú konstruktor / gyári módszer a String értékből deserializálni ('The Parish Boy's Progress')

Ennek a viselkedésnek ismét értelme van. Lényegében Jacksonnak olyan konstruktorra van szüksége, amely képes felvenni az értékét felirat érvként. A mi esetünkben nem ez a helyzet Választható terület.

3. Megoldás

Amit akarunk, az az, hogy Jackson egy üreset kezeljen Választható mint nulla, és egy ajándék kezelésére Választható mint az értékét képviselő mező.

Szerencsére ez a probléma megoldódott számunkra. Jacksonnak van egy sor modulja, amelyek a JDK 8 adattípusokkal foglalkoznak Választható.

3.1. Maven Függőség és regisztráció

Először adjuk hozzá a legújabb verziót Maven-függőségként:

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

Most csak annyit kell tennünk, hogy regisztráljuk a modult a ObjectMapper:

ObjectMapper mapper = új ObjectMapper (); mapper.registerModule (új Jdk8Module ());

3.2. Serializálás

Most teszteljük. Ha megpróbáljuk sorosítani a Könyv megint látni fogjuk, hogy van egy felirat, szemben a beágyazott JSON-nal:

Könyvkönyv = új Könyv (); book.setTitle ("Oliver Twist"); book.setSubTitle (Opcionális.of ("A plébános fiú haladása")); String serializedBook = mapper.writeValueAsString (könyv); assertThat (from (serializedBook) .getString ("subTitle")) .isEqualTo ("A plébános fiú haladása");

Ha megpróbálunk egy üres könyvet sorosítani, akkor az a nulla:

book.setSubTitle (Opcionális.empty ()); String serializedBook = mapper.writeValueAsString (könyv); assertThat (from (serializedBook) .getString ("subTitle")). isNull ();

3.3. Deserializáció

Most ismételjük meg a deserializációs teszteket. Ha újraolvassuk a Könyvünket, látni fogjuk, hogy már nem kapunk egy JsonMappingException:

Book newBook ​​= mapper.readValue (eredmény, Könyv.osztály); assertThat (newBook.getSubTitle ()). isEqualTo (Opcionális.of ("A plébános fiú haladása"));

Végül ismételjük meg újra a tesztet, ezúttal a nulla. Meglátjuk, hogy még egyszer nem kapunk egy JsonMappingException, és valójában legyen egy üres Választható:

assertThat (newBook.getSubTitle ()). isEqualTo (Opcionális.empty ());

4. Következtetés

Megmutattuk, hogyan lehet kiküszöbölni ezt a problémát a JDK 8 DataTypes modul kihasználásával, bemutatva, hogyan lehet Jackson számára kezelni egy Választható mint nulla, és egy ajándék Választható mint hétköznapi mező.

Ezeknek a példáknak a megvalósítása megtalálható a GitHub oldalon; ez egy Maven-alapú projekt, ezért könnyen futtathatónak kell lennie.