A YAML elemzése a SnakeYAML segítségével

1. Áttekintés

Ebben az oktatóanyagban megtanuljuk, hogyan kell használni a SnakeYAML könyvtárat sorosítsa a Java objektumokat YAML dokumentumokká és fordítva.

2. Projekt beállítása

A SnakeYAML használatához projektünkben hozzáadjuk a következő Maven-függőséget (a legújabb verzió itt található):

 org.yaml snakeyaml 1.21 

3. Belépési pont

A Yaml osztály az API belépési pontja:

Yaml yaml = új Yaml ();

Mivel a megvalósítás nem szálbiztos, a különféle szálaknak meg kell lenniük a sajátjuknak Yaml példa.

4. YAML dokumentum betöltése

A könyvtár támogatást nyújt a dokumentum betöltéséhez a Húr vagy egy InputStream. A kódminták többsége itt a. Elemzésén alapul InputStream.

Kezdjük azzal, hogy definiálunk egy egyszerű YAML dokumentumot, és a fájlt elnevezzük ügyfél.yaml:

keresztnév: "John" vezetéknév: "Doe" életkor: 20

4.1. Alapvető használat

Most a fenti YAML dokumentumot elemezzük a Yaml osztály:

Yaml yaml = új Yaml (); InputStream inputStream = this.getClass () .getClassLoader () .getResourceAsStream ("customer.yaml"); Map obj = yaml.load (inputStream); System.out.println (obj);

A fenti kód a következő kimenetet generálja:

{keresztnév = János, vezetéknév = őz, kor = 20}

Alapértelmezés szerint a Betöltés() metódus a Térkép példa. A. Lekérdezése Térkép Az objektum minden egyes megkövetelése esetén előre meg kell ismernünk a tulajdonságkulcsok nevét, és az sem egyszerű, ha bejárjuk a beágyazott tulajdonságokat.

4.2. Egyéni típus

A könyvtár is lehetőséget nyújt a dokumentum egyéni osztályként történő betöltésére. Ez az opció lehetővé tenné az adatok egyszerű áthaladását a memóriában.

Határozzuk meg a Vevő osztályban, és próbálja újra betölteni a dokumentumot:

public class Ügyfél {private String keresztnév; privát karakterlánc vezetéknév; privát int kor; // szerelők és beállítók}

Feltételezve, hogy a YAML dokumentumot deszerializálják, mint ismert típust, megadhatunk egy explicit globált címke a dokumentumban.

Frissítsük a dokumentumot, és tároljuk egy új fájlban customer_with_type.yaml:

!! com.baeldung.snakeyaml.Customer firstName: "John" lastName: "Doe" age: 20

Vegye figyelembe a dokumentum első sorát, amely tartalmazza a betöltéskor használandó osztályra vonatkozó információkat.

Most frissítjük a fent használt kódot, és megadjuk az új fájlnevet bemenetként:

Yaml yaml = új Yaml (); InputStream inputStream = this.getClass () .getClassLoader () .getResourceAsStream ("yaml / customer_with_type.yaml"); Ügyfél ügyfél = yaml.load (inputStream); 

A Betöltés() A metódus most a Vevő típus. Ennek a megközelítésnek az a hátránya, hogy a típust könyvtárként kell exportálni, hogy szükség esetén felhasználható legyen.

Bár használhatnánk az explicit helyi címkét, amelyhez nem kötelező a könyvtárak exportálása.

Az egyéni típus betöltésének másik módja a Konstruktőr osztály. Így megadhatjuk a feldolgozandó YAML-dokumentum gyökér típusát. Hozzunk létre egy Konstruktőr például a Vevő írja be root típusként, és adja át a Yaml példa.

Most a customer.yaml, megkapjuk a Vevő tárgy:

Yaml yaml = new Yaml (new Constructor (Customer.class));

4.3. Implicit típusok

Abban az esetben, ha egy adott tulajdonsághoz nincs meghatározva típus, a könyvtár automatikusan átalakítja az értéket implicit típusgá.

Például:

1.0 -> Úszó 42 -> Egész 2009-03-30 -> Dátum

Teszteljük ezt az implicit típusú konverziót egy tesztesettel:

@Test public void whenLoadYAML_thenLoadCorrectImplicitTypes () {Yaml yaml = new Yaml (); Térképdokumentum = yaml.load ("3.0: 2018-07-22"); assertNotNull (dokumentum); assertEquals (1, document.size ()); assertTrue (document.containsKey (3.0d)); }

4.4. Beágyazott objektumok és gyűjtemények

Ha egy legfelső szintű típust kap, a könyvtár automatikusan felismeri a beágyazott objektumok típusait, hacsak nem interfész vagy elvont osztály, és deserializálja a dokumentumot a megfelelő beágyazott típusra.

Tegyük hozzá Kapcsolatba lépni és Cím részletek a customer.yaml, és mentse az új fájlt customer_with_contact_details_and_address.yaml.

Most elemezzük az új YAML dokumentumot:

keresztnév: "John" vezetéknév: "Doe" életkor: 31 kapcsolatRészletek: - típus: "mobil" szám: 123456789 - típus: "vezetékes" szám: 456786868 homeCím: vonal: "Xyz, DEF utca" város: "City Y" állapot : "Y állam" irányítószám: 345657 

Vevő osztálynak is tükröznie kell ezeket a változásokat. Itt van a frissített osztály:

public class Ügyfél {private String keresztnév; privát karakterlánc vezetéknév; privát int kor; privát Lista contactDetails; privát Cím homeAddress; // szerelők és beállítók} 

Lássuk, hogyan Kapcsolatba lépni és Cím osztályok néz ki:

public class Kapcsolat {private String type; privát int szám; // szerelők és beállítók}
public class Cím {private String line; privát String város; privát String állam; magán egész szám cipzár; // szerelők és beállítók}

Most teszteljük a Yaml#Betöltés() az adott tesztesettel:

@Test public void whenLoadYAMLDocumentWithTopLevelClass_thenLoadCorrectJavaObjectWithNestedObjects () {Yaml yaml = new Yaml (new Constructor (Customer.class)); InputStream inputStream = this.getClass () .getClassLoader () .getResourceAsStream ("yaml / customer_with_contact_details_and_address.yaml"); Ügyfél ügyfél = yaml.load (inputStream); assertNotNull (ügyfél); assertEquals ("John", customer.getFirstName ()); assertEquals ("Doe", customer.getLastName ()); assertEquals (31, ügyfél.getAge ()); assertNotNull (customer.getContactDetails ()); assertEquals (2, customer.getContactDetails (). size ()); assertEquals ("mobile", customer.getContactDetails () .get (0) .getType ()); assertEquals (123456789, customer.getContactDetails () .get (0) .getNumber ()); assertEquals ("vezetékes", customer.getContactDetails () .get (1) .getType ()); assertEquals (456786868, customer.getContactDetails () .get (1) .getNumber ()); assertNotNull (customer.getHomeAddress ()); assertEquals ("Xyz, DEF utca", customer.getHomeAddress () .getLine ()); }

4.5. Típusbiztos gyűjtemények

Ha egy adott Java osztály egy vagy több tulajdonsága típusbiztos (általános) gyűjtemény, akkor fontos megadni azt TypeDescription hogy a helyes paraméterezett típust azonosítsák.

Vegyünk egyet Vevő több is van Kapcsolatba lépni, és próbálja meg betölteni:

keresztnév: "John" vezetéknév: "Doe" életkor: 31 contactDetails: - {type: "mobile", number: 123456789} - {type: "landline", number: 123456789}

A dokumentum betöltése érdekében megadhatjuk a TypeDescription az adott tulajdonságra a legfelső szintű osztályon:

Konstruktor konstruktor = new Konstruktor (Customer.class); TypeDescription customTypeDescription = új TypeDescription (Customer.class); customTypeDescription.addPropertyParameters ("contactDetails", Contact.class); constructor.addTypeDescription (customTypeDescription); Yaml yaml = új Yaml (konstruktor);

4.6. Több dokumentum betöltése

Lehetnek olyan esetek, amikor egyetlen File több YAML dokumentum létezik, és mindegyiket fel akarjuk elemezni. A Yaml osztály biztosítja a loadAll () módszer ilyen típusú elemzésre.

Alapértelmezés szerint a metódus visszaadja a Iterálható ahol minden objektum típusú Térkép. Ha egyedi típusra van szükség, akkor használhatjuk a Konstruktőr a fentiekben tárgyaltak szerint.

Vegye figyelembe a következő dokumentumokat egyetlen fájlban:

--- keresztnév: "John" vezetéknév: "Doe" kor: 20 --- keresztnév: "Jack" vezetéknév: "Jones" életkor: 25

A fentieket elemezhetjük a loadAll () módszer az alábbi kódminta szerint:

@Test public void whenLoadMultipleYAMLDocuments_thenLoadCorrectJavaObjects () {Yaml yaml = new Yaml (new Constructor (Customer.class)); InputStream inputStream = this.getClass () .getClassLoader () .getResourceAsStream ("yaml / customers.yaml"); int szám = 0; for (Object object: yaml.loadAll (inputStream)) {count ++; assertTrue (az Ügyfél objektum példánya); } assertEquals (2, szám); }

5. A YAML-dokumentumok dömpingje

A könyvtár egy módszert is biztosít a adott Java objektumot helyezzen el egy YAML dokumentumba. A kimenet lehet a Húr vagy egy megadott fájl / adatfolyam.

5.1. Alapvető használat

Egy egyszerű példával kezdjük a példány dömpingjét Térkép YAML dokumentumhoz (Húr):

@Test public void whenDumpMap_thenGenerateCorrectYAML () {Map data = new LinkedHashMap (); data.put ("név", "Silenthand Olleander"); data.put ("faj", "Ember"); data.put ("vonások", új karakterlánc [] {"ONE_HAND", "ONE_EYE"}); Yaml yaml = új Yaml (); StringWriter író = new StringWriter (); yaml.dump (adat, író); Karakterlánc várhatóYaml = "név: Silenthand Olleander \ nrace: Emberi \ ntképek: [ONE_HAND, ONE_EYE] \ n"; assertEquals (várhatóYaml, író.toString ()); }

A fenti kód a következő kimenetet hozza létre (vegye figyelembe, hogy a LinkedHashMap megőrzi a kimeneti adatok sorrendjét):

név: Silenthand Olleander faj: Emberi tulajdonságok: [ONE_HAND, ONE_EYE]

5.2. Egyéni Java objektumok

Mi is választhatunk dobja ki az egyedi Java típusokat egy kimeneti adatfolyamba. Ez azonban hozzáadja a globális explicit szót címke a kimeneti dokumentumhoz:

@Test public void whenDumpACustomType_thenGenerateCorrectYAML () {Ügyfél ügyfél = új Ügyfél (); customer.setAge (45); customer.setFirstName ("Greg"); customer.setLastName ("McDowell"); Yaml yaml = új Yaml (); StringWriter író = new StringWriter (); yaml.dump (megrendelő, író); Karakterlánc várhatóYaml = "!! com.baeldung.snakeyaml.Customer {age: 45, contactDetails: null, firstName: Greg, \ n homeCím: null, lastName: McDowell} \ n"; assertEquals (várhatóYaml, író.toString ()); }

A fenti megközelítéssel a címkeinformációkat továbbra is a YAML dokumentumba dobjuk.

Ez azt jelenti, hogy könyvtárunkat kell exportálnunk minden fogyasztó számára, aki deserializálja azt. A kimeneti fájlban a címke neve elkerülése érdekében használhatjuk a dumpAs () a könyvtár által biztosított módszer.

Tehát a fenti kódban a következőket csíptük a címke eltávolításához:

yaml.dumpAs (ügyfél, Tag.MAP, null);

6. Következtetés

Ez a cikk bemutatta a SnakeYAML könyvtár használatát a Java objektumok YAML-be való sorosítására és viszont.

Az összes példa megtalálható a GitHub projektben - ez egy Maven alapú projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.