Analýza YAML s SnakeYAML

1. Prehľad

V tomto tutoriále sa naučíme, ako používať knižnicu SnakeYAML na serializovať objekty Java na dokumenty YAML a naopak.

2. Nastavenie projektu

Aby sme v našom projekte mohli použiť SnakeYAML, pridáme nasledujúcu závislosť Maven (najnovšiu verziu nájdete tu):

 org.yaml snakeyaml 1.21 

3. Vstupný bod

The Yaml trieda je vstupným bodom pre API:

Yaml yaml = nový Yaml ();

Pretože implementácia nie je bezpečná pre rôzne vlákna, rôzne vlákna musia mať svoje vlastné Yaml inštancia.

4. Vloženie dokumentu YAML

Knižnica poskytuje podporu pre načítanie dokumentu z a String alebo an InputStream. Väčšina vzorových kódov by tu bola založená na analýze súboru InputStream.

Začnime definovaním jednoduchého dokumentu YAML a pomenovaním súboru ako zákazník.yaml:

meno: "John" priezvisko: "Laň" vek: 20

4.1. Základné použitie

Teraz analyzujeme vyššie uvedený dokument YAML s Yaml trieda:

Yaml yaml = nový Yaml (); InputStream inputStream = this.getClass () .getClassLoader () .getResourceAsStream ("customer.yaml"); Mapa obj = yaml.load (inputStream); System.out.println (obj);

Vyššie uvedený kód generuje nasledujúci výstup:

{firstName = John, lastName = Laň, vek = 20}

V predvolenom nastavení je naložiť() metóda vracia a Mapa inštancia. Dopytujem Mapa objekt by zakaždým vyžadoval, aby sme vopred poznali názvy kľúčov vlastností a tiež nie je ľahké prechádzať cez vnorené vlastnosti.

4.2. Vlastný typ

Knižnica tiež poskytuje spôsob načítania dokumentu ako vlastnej triedy. Táto možnosť by umožnila ľahký prechod údajov v pamäti.

Definujme a Zákazník triedy a skúste dokument načítať znova:

verejná trieda Zákazník {private String firstName; private String priezvisko; súkromný int vek; // zakladatelia a zakladatelia}

Za predpokladu, že bude dokument YAML deserializovaný ako známy typ, môžeme určiť explicitný globálny značka v dokumente.

Aktualizujme dokument a uložme ho do nového súboru customer_with_type.yaml:

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

Všimnite si prvý riadok v dokumente, ktorý obsahuje informácie o triede, ktorá sa má použiť pri načítaní.

Teraz aktualizujeme vyššie použitý kód a zadáme nový názov súboru ako vstup:

Yaml yaml = nový Yaml (); InputStream inputStream = this.getClass () .getClassLoader () .getResourceAsStream ("yaml / customer_with_type.yaml"); Zákazník zákazník = yaml.load (inputStream); 

The naložiť() metóda teraz vracia inštanciu Zákazník typu. Nevýhodou tohto prístupu je, že typ sa musí exportovať ako knižnica, aby sa mohol v prípade potreby použiť.

Mohli by sme však použiť explicitnú miestnu značku, pre ktorú nie sme povinní exportovať knižnice.

Ďalším spôsobom načítania vlastného typu je použitie Konštruktér trieda. Týmto spôsobom môžeme určiť koreňový typ dokumentu YAML, ktorý sa má analyzovať. Vytvorme Konštruktér napríklad s Zákazník zadajte ako koreňový typ a odovzdajte ho Yaml inštancia.

Teraz pri načítaní súboru customer.yaml, dostaneme Zákazník objekt:

Yaml yaml = nový Yaml (nový konštruktér (Customer.class));

4.3. Implicitné typy

V prípade, že pre danú vlastnosť nie je definovaný žiadny typ, knižnica automaticky prevedie hodnotu na implicitný typ.

Napríklad:

1.0 -> Float 42 -> Integer 2009-03-30 -> Date

Vyskúšajme túto implicitnú konverziu typu pomocou testovacieho prípadu:

@Test public void whenLoadYAML_thenLoadCorrectImplicitTypes () {Yaml yaml = nový Yaml (); Mapový dokument = yaml.load ("3.0: 2018-07-22"); assertNotNull (dokument); assertEquals (1, document.size ()); assertTrue (document.containsKey (3.0d)); }

4.4. Vnorené objekty a zbierky

Knižnica má typ najvyššej úrovne a automaticky detekuje typy vnorených objektov, pokiaľ nejde o rozhranie alebo abstraktnú triedu, a deserializuje dokument na príslušný vnorený typ.

Pridajme Kontakt a Adresa podrobnosti k customer.yaml, a uložte nový súbor ako customer_with_contact_details_and_address.yaml.

Teraz rozoberieme nový dokument YAML:

firstName: "John" lastName: "Doe" age: 31 contactDetails: - type: "mobile" number: 123456789 - type: "landline" number: 456786868 homeAddress: line: "Xyz, DEF Street" city: "City Y" state : „Štát Y“ PSČ: 345657 

Zákazník triedy by mali odrážať aj tieto zmeny. Tu je aktualizovaná trieda:

verejná trieda Zákazník {private String firstName; private String priezvisko; súkromný int vek; súkromný zoznam contactDetails; súkromná adresa homeAddress; // zakladatelia a zakladatelia} 

Uvidíme ako Kontakt a Adresa triedy vyzerajú takto:

public class Contact {private String type; súkromné ​​int číslo; // zakladatelia a zakladatelia}
public class Adresa {private String line; súkromné ​​mesto String; súkromný štát reťazca; súkromné ​​celé číslo; // zakladatelia a zakladatelia}

Teraz otestujeme Yaml#naložiť() s daným testovacím prípadom:

@Test public void whenLoadYAMLDocumentWithTopLevelClass_thenLoadCorrectJavaObjectWithNestedObjects () {Yaml yaml = nový Yaml (nový konštruktér (Customer.class)); InputStream inputStream = this.getClass () .getClassLoader () .getResourceAsStream ("yaml / customer_with_contact_details_and_address.yaml"); Zákazník zákazník = yaml.load (inputStream); assertNotNull (zákazník); assertEquals ("John", customer.getFirstName ()); assertEquals ("Doe", customer.getLastName ()); assertEquals (31, customer.getAge ()); assertNotNull (customer.getContactDetails ()); assertEquals (2, customer.getContactDetails (). size ()); assertEquals ("mobile", customer.getContactDetails () .get (0) .getType ()); assertEquals (123456789, customer.getContactDetails () .get (0) .getNumber ()); assertEquals ("pevná linka", customer.getContactDetails () .get (1) .getType ()); assertEquals (456786868, customer.getContactDetails () .get (1) .getNumber ()); assertNotNull (customer.getHomeAddress ()); assertEquals ("Xyz, DEF Street", customer.getHomeAddress () .getLine ()); }

4.5. Typovo bezpečné zbierky

Ak sú jedna alebo viac vlastností danej triedy Java typovo bezpečné (všeobecné) kolekcie, je dôležité určiť Typ Popis aby bol identifikovaný správny typ parametrizácie.

Zoberme si jednu Zákazník mať viac ako jednu Kontakta skúste ho načítať:

firstName: "John" lastName: "Doe" vek: 31 contactDetails: - {type: "mobile", number: 123456789} - {type: "landline", number: 123456789}

Na načítanie tohto dokumentu môžeme určiť Typ Popis pre danú nehnuteľnosť v triede najvyššej úrovne:

Konštruktor konštruktor = nový konštruktor (Customer.class); TypeDescription customTypeDescription = nový TypeDescription (Customer.class); customTypeDescription.addPropertyParameters ("contactDetails", Contact.class); constructor.addTypeDescription (customTypeDescription); Yaml yaml = nový Yaml (konštruktor);

4.6. Načítanie viacerých dokumentov

Môžu sa vyskytnúť prípady, keď v jednom Súbor existuje niekoľko dokumentov YAML a všetky z nich chceme analyzovať. The Yaml trieda poskytuje a loadAll () spôsob vykonania takéhoto typu syntaktickej analýzy.

V predvolenom nastavení metóda vracia inštanciu Iterable kde každý objekt je typu Mapa. Ak je požadovaný vlastný typ, môžeme použiť Konštruktér inštancie, ako je uvedené vyššie.

Zvážte nasledujúce dokumenty v jednom súbore:

--- meno: "John" priezvisko: "Laň" vek: 20 --- meno: "Jack" priezvisko: "Jones" vek: 25

Vyššie uvedené môžeme analyzovať pomocou loadAll () metóda uvedená v nasledujúcej ukážke kódu:

@Test public void whenLoadMultipleYAMLDocuments_thenLoadCorrectJavaObjects () {Yaml yaml = nový Yaml (nový konštruktér (Customer.class)); InputStream inputStream = this.getClass () .getClassLoader () .getResourceAsStream ("yaml / customers.yaml"); počet int = 0; pre (Object object: yaml.loadAll (inputStream)) {count ++; assertTrue (inštancia objektu zákazníka); } assertEquals (2; pocet); }

5. Dumpingové dokumenty YAML

Knižnica tiež poskytuje metódu vypísať daný objekt Java do dokumentu YAML. Výstupom môže byť a String alebo zadaný súbor / stream.

5.1. Základné použitie

Začneme jednoduchým príkladom výpisu inštancie z Mapa k dokumentu YAML (String):

@Test public void whenDumpMap_thenGenerateCorrectYAML () {Map data = new LinkedHashMap (); data.put ("meno", "Silenthand Olleander"); data.put ("závod", "človek"); data.put ("vlastnosti", nový reťazec [] {"ONE_HAND", "ONE_EYE"}); Yaml yaml = nový Yaml (); Zapisovateľ StringWriter = nový StringWriter (); yaml.dump (údaje, zapisovateľ); Reťazec expectYaml = "meno: Silenthand Olleander \ nrace: Human \ ntraits: [ONE_HAND, ONE_EYE] \ n"; assertEquals (expectYaml, writer.toString ()); }

Vyššie uvedený kód produkuje nasledujúci výstup (všimnite si, že pomocou inštancie LinkedHashMap zachováva poradie výstupných údajov):

meno: Silenthand Olleander závod: Ľudské vlastnosti: [ONE_HAND, ONE_EYE]

5.2. Prispôsobené objekty Java

Môžeme sa tiež rozhodnúť výpis vlastných typov Java do výstupného toku. Toto však pridá globálny explicitný výraz značka do výstupného dokumentu:

@ Test public void whenDumpACustomType_thenGenerateCorrectYAML () {Zákazník zákazník = nový Zákazník (); customer.setAge (45); customer.setFirstName ("Greg"); customer.setLastName ("McDowell"); Yaml yaml = nový Yaml (); Zapisovateľ StringWriter = nový StringWriter (); yaml.dump (zákazník, autor); Reťazec expectYaml = "!! com.baeldung.snakeyaml.Customer {vek: 45 rokov, contactDetails: null, meno: Greg, \ n homeAddress: null, priezvisko: McDowell} \ n"; assertEquals (expectYaml, writer.toString ()); }

S vyššie uvedeným prístupom stále ukladáme informácie o značke v dokumente YAML.

To znamená, že musíme exportovať našu triedu ako knižnicu pre všetkých spotrebiteľov, ktorí ju deserializujú. Aby sme sa vyhli názvu značky vo výstupnom súbore, môžeme použiť znak dumpAs () metóda poskytovaná knižnicou.

Vo vyššie uvedenom kóde by sme teda mohli značku odstrániť:

yaml.dumpAs (zákazník, Tag.MAP, null);

6. Záver

Tento článok ilustroval použitie knižnice SnakeYAML na serializáciu objektov Java na YAML a naopak.

Všetky príklady nájdete v projekte GitHub - jedná sa o projekt založený na Maven, takže by malo byť ľahké ho importovať a spustiť tak, ako je.


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