XStream-gebruikershandleiding: objecten converteren naar XML

1. Overzicht

In deze zelfstudie leren we hoe u de XStream-bibliotheek kunt gebruiken om Java-objecten naar XML te serialiseren.

2. Kenmerken

Er zijn nogal wat interessante voordelen aan het gebruik van XStream om XML te serialiseren en deserialiseren:

  • Goed geconfigureerd, produceert het zeer schone XML
  • Biedt aanzienlijke kansen voor maatwerk van de XML-uitvoer
  • Ondersteuning voor object grafieken, inclusief circulaire verwijzingen
  • In de meeste gevallen is de XStream-instantie thread-safe, eenmaal geconfigureerd (er zijn kanttekeningen bij het gebruik van annotaties)
  • Tijdens afhandeling van uitzonderingen om problemen te helpen diagnosticeren
  • Vanaf versie 1.4.7 hebben we beveiligingsfuncties beschikbaar om serialisatie van bepaalde typen niet toe te staan

3. Projectconfiguratie

Om XStream in ons project te gebruiken, zullen we de volgende Maven-afhankelijkheid toevoegen:

 com.thoughtworks.xstream xstream 1.4.9 

4. Basisgebruik

De XStream class is een façade voor de API. Bij het maken van een instantie van XStream, we moeten ook zorgen voor problemen met de draadveiligheid:

XStream xstream = nieuwe XStream ();

Als een instantie eenmaal is gemaakt en geconfigureerd, kan deze worden gedeeld over meerdere threads voor rangschikking / unmarshalling, tenzij u annotatieverwerking inschakelt.

4.1. Bestuurders

Er worden verschillende stuurprogramma's ondersteund, zoals DomDriver, StaxDriver, XppDriver, en meer. Deze stuurprogramma's hebben verschillende kenmerken voor prestaties en resourcegebruik.

De XPP3-driver wordt standaard gebruikt, maar we kunnen de driver natuurlijk eenvoudig wijzigen:

XStream xstream = nieuwe XStream (nieuwe StaxDriver ()); 

4.2. XML genereren

Laten we beginnen met het definiëren van een eenvoudige POJO voor - Klant:

openbare klasse Klant {private String firstName; private String achternaam; privé Datum dob; // standard constructor, setters en getters}

Laten we nu een XML-weergave van het object genereren:

Klant klant = nieuwe klant ("Jan", "Doe", nieuwe datum ()); String dataXml = xstream.toXML (klant);

Met de standaardinstellingen wordt de volgende uitvoer geproduceerd:

 John Doe 1986-02-14 03: 46: 16.381 UTC 

Uit deze uitvoer kunnen we duidelijk zien dat de bevattende tag de volledig gekwalificeerde klassenaam van gebruikt Klant standaard.

Er zijn veel redenen waarom we zouden kunnen besluiten dat het standaardgedrag niet past bij onze behoeften. Het kan bijvoorbeeld zijn dat we ons niet op ons gemak voelen om de pakketstructuur van onze applicatie bloot te leggen. Ook is de gegenereerde XML aanzienlijk langer.

5. Aliassen

Een alias is een naam die we willen gebruiken voor elementen in plaats van standaardnamen te gebruiken.

We kunnen bijvoorbeeld vervangen com.baeldung.pojo.Customer met klant door een alias te registreren voor het Klant klasse. We kunnen ook aliassen toevoegen voor eigenschappen van een klasse. Door aliassen te gebruiken, kunnen we onze XML-output veel leesbaarder en minder Java-specifiek maken.

5.1. Klasse-aliassen

Aliassen kunnen programmatisch of met behulp van annotaties worden geregistreerd.

Laten we nu onze Klant les met @RTLnieuws:

@XStreamAlias ​​("klant")

Nu moeten we onze instantie configureren om deze annotatie te gebruiken:

xstream.processAnnotations (Customer.class);

Als we een alias programmatisch willen configureren, kunnen we ook de onderstaande code gebruiken:

xstream.alias ("klant", Customer.class);

Of u nu de alias of de programmaconfiguratie gebruikt, de uitvoer voor een Klant object zal veel schoner zijn:

 John Doe 1986-02-14 03: 46: 16.381 UTC 

5.2. Veld Aliassen

We kunnen ook aliassen voor velden toevoegen met dezelfde annotatie die wordt gebruikt voor aliasingklassen. Als we bijvoorbeeld het veld wilden Voornaam worden vervangen door fn in de XML-weergave zouden we de volgende annotatie kunnen gebruiken:

@XStreamAlias ​​("fn") private String firstName;

Als alternatief kunnen we hetzelfde doel programmatisch bereiken:

xstream.aliasField ("fn", Customer.class, "firstName");

De aliasField method accepteert drie argumenten: de alias die we willen gebruiken, de klasse waarin de eigenschap is gedefinieerd en de eigenschapsnaam die we willen alias.

Welke methode ook wordt gebruikt, de uitvoer is hetzelfde:

 John Doe 1986-02-14 03: 46: 16.381 UTC 

5.3. Standaard Aliassen

Er zijn verschillende aliassen die vooraf zijn geregistreerd voor klassen - hier zijn er een paar:

alias ("float", Float.class); alias ("date", Date.class); alias ("gregoriaanse kalender", Calendar.class); alias ("url", URL.class); alias ("lijst", List.class); alias ("locale", Locale.class); alias ("valuta", Currency.class);

6. Collecties

Nu zullen we een lijst met Contact details binnen in de Klant klasse.

privélijst contactDetailsList;

Met standaardinstellingen voor het afhandelen van verzamelingen, is dit de uitvoer:

 John Doe 1986-02-14 04: 14: 05.874 UTC 6673543265 0124-2460311 4676543565 0120-223312 

Stel dat we de contactDetailsList bovenliggende tags, en we willen gewoon elk Contact details element om een ​​kind te zijn van de klant element. Laten we ons voorbeeld opnieuw aanpassen:

xstream.addImplicitCollection (Customer.class, "contactDetailsList");

Nu, wanneer de XML wordt gegenereerd, worden de root-tags weggelaten, wat resulteert in de onderstaande XML:

 John Doe 1986-02-14 04: 14: 20.541 UTC 6673543265 0124-2460311 4676543565 0120-223312 

Hetzelfde kan ook worden bereikt met annotaties:

@XStreamImplicit privélijst contactDetailsList;

7. Omvormers

XStream gebruikt een kaart van Converter instanties, elk met zijn eigen conversiestrategie. Deze zetten aangeleverde data om naar een bepaald formaat in XML en weer terug.

Naast het gebruik van de standaard converters, kunnen we de standaardinstellingen wijzigen of aangepaste converters registreren.

7.1. Een bestaande converter wijzigen

Stel dat we niet blij waren met de manier waarop de dob tags zijn gegenereerdmet de standaardinstellingen. We kunnen de aangepaste converter aanpassen voor Datum geleverd door XStream (DateConverter):

xstream.registerConverter (nieuwe DateConverter ("dd-MM-jjjj", null));

Het bovenstaande zal de output produceren in “dd-MM-jjjj"Formaat:

 John Doe 14-02-1986 

7.2. Aangepaste converters

We kunnen ook een aangepaste converter maken om dezelfde uitvoer te bereiken als in de vorige sectie:

openbare klasse MyDateConverter implementeert Converter {privé SimpleDateFormat-formatter = nieuwe SimpleDateFormat ("dd-MM-jjjj"); @Override openbare boolean canConvert (Class clazz) {return Date.class.isAssignableFrom (clazz); } @Override public void marshal (Objectwaarde, HierarchicalStreamWriter-schrijver, MarshallingContext arg2) {Date date = (Date) waarde; writer.setValue (formatter.format (datum)); } // andere methodes }

Ten slotte registreren we onze MyDateConverter klasse zoals hieronder:

xstream.registerConverter (nieuwe MyDateConverter ());

We kunnen ook converters maken die het SingleValueConverter interface, die is ontworpen om een ​​object in een string te converteren.

openbare klasse MySingleValueConverter implementeert SingleValueConverter {@Override openbare boolean canConvert (Class clazz) {return Customer.class.isAssignableFrom (clazz); } @Override public String toString (Object obj) {SimpleDateFormat formatter = new SimpleDateFormat ("dd-MM-yyyy"); Datum datum = ((Klant) obj) .getDob (); return ((Customer) obj) .getFirstName () + "," + ((Customer) obj) .getLastName () + "," + formatter.format (date); } // andere methodes }

Ten slotte registreren we MySingleValueConverter:

xstream.registerConverter (nieuwe MySingleValueConverter ()); 

Gebruik makend van MySingleValueConverter, de XML-uitvoer voor een Klant is als volgt:

John, Doe, 14-02-1986

7.3. Converter prioriteit

Bij het registreren Converter objecten, is het ook mogelijk om hun prioriteitsniveau in te stellen.

Van de XStream javadocs:

De converters kunnen worden geregistreerd met een expliciete prioriteit. Standaard zijn ze geregistreerd bij XStream.PRIORITY_NORMAL. Omvormers met dezelfde prioriteit worden gebruikt in de omgekeerde volgorde waarin ze zijn geregistreerd. De standaard converter, d.w.z. de converter die zal worden gebruikt als geen andere geregistreerde converter geschikt is, kan worden geregistreerd met prioriteit XStream.PRIORITY_VERY_LOW. XStream gebruikt standaard de ReflectionConverter als de fallback-converter.

De API biedt verschillende benoemde prioriteitswaarden:

privé statische definitieve int PRIORITY_NORMAL = 0; privé statische laatste int PRIORITY_LOW = -10; privé statische laatste int PRIORITY_VERY_LOW = -20; 

8.Velden weglaten

We kunnen velden weglaten uit onze gegenereerde XML met behulp van annotaties of programmatische configuratie. Om een ​​veld weg te laten met een annotatie, passen we eenvoudig de @RTLnieuws annotatie bij het betreffende veld:

@XStreamOmitField private String firstName;

Om het veld programmatisch weg te laten, gebruiken we de volgende methode:

xstream.omitField (Customer.class, "firstName");

Welke methode we ook selecteren, de output is hetzelfde:

 Doe 14-02-1986 

9. Kenmerkvelden

Soms willen we een veld liever serialiseren als een attribuut van een element dan als element zelf. Stel dat we een contact type veld:

privé String contactType;

Als we willen instellen contact type als XML-attribuut kunnen we de @XStreamAsAttribute annotatie:

@XStreamAsAttribute privé String contactType; 

Als alternatief kunnen we hetzelfde doel programmatisch bereiken:

xstream.useAttributeFor (ContactDetails.class, "contactType");

De output van een van de bovenstaande methoden is hetzelfde:

 6673543265 0124-2460311 

10. Gelijktijdigheid

Het verwerkingsmodel van XStream biedt enkele uitdagingen. Zodra de instantie is geconfigureerd, is deze thread-safe.

Het is belangrijk op te merken dat de verwerking van annotaties de configuratie wijzigt net voor het rangschikken / verwijderen van de marges. En dus - als we vereisen dat de instantie on-the-fly wordt geconfigureerd met behulp van annotaties, is het over het algemeen een goed idee om een ​​aparte XStream bijvoorbeeld voor elke thread.

11. Conclusie

In dit artikel hebben we de basisprincipes besproken van het gebruik van XStream om objecten naar XML te converteren. We hebben ook geleerd over aanpassingen die we kunnen gebruiken om ervoor te zorgen dat de XML-uitvoer aan onze behoeften voldoet. Ten slotte hebben we gekeken naar problemen met thread-veiligheid met annotaties.

In het volgende artikel in deze serie zullen we leren over het terug converteren van XML naar Java-objecten.

De volledige broncode voor dit artikel kan worden gedownload vanuit de gekoppelde GitHub-repository.