YAML Ain't Markup Language (YAML)
Eintrag zuletzt aktualisiert am: 12.06.2019
YAML ist ein textbasiertes
Datenformat in Form einer Auszeichnungssprache. Eine Auszeichnungssprache (englisch Markup Language) ist laut [
https://de.wikipedia.org/wiki/Auszeichnungssprache] eine maschinenlesbare Sprache für die Gliederung und Formatierung von Texten und anderen Daten. Bekanntere Auszeichnungssprachen sind HTML,
XML und
JSON. YAML zeichnet sich gegenüber HTML,
XML und
JSON dadurch aus, dass es kompakter und übersichtlicher ist; daher ist es nicht nur für Maschinen, sondern auch für Menschen gut lesbar.
Einsatzgebiete von YAML
YAML wird inzwischen an einigen Stellen als Konfigurationsformat eingesetzt, z.B. in
Docker,
Kubernetes und seit 2019 auch in
Azure DevOps-
Pipelines zur Definition von Continous Integration- und Continous Delivery-
Prozessen. Grundsätzlich kann YAML aber nicht nur für
Konfigurationsdateien, sondern als beliebiges
Datenformat eingesetzt werden, auch als Ersatz für
XML und
JSON.
Es gibt zahlreiche
Softwarekomponenten zur Serialisierung von
Objektmodellen in YAML bzw. der
Deserialisierung von YAML in
Objektmodellen in zahlreichen
Programmiersprachen und Frameworks, z.B. C, C++,
Ruby,
Python, Java,
Perl, .NET,
PHP,
Dart,
JavaScript (siehe [
https://yaml.org/]).
Name YAML
Die Abkürzung YAML stand ursprünglich für "Yet Another Markup Language". Mittlerweile verwendet man YAML als rekursive Abkürzung für "YAML Ain’t Markup Language".
Versionen
Die erste Version der YAML-Sepzifikation von Oren Ben-Kiki, Clark Evans und Brian Ingerson stammt bereits vom 29.2.2004 [
https://yaml.org/spec/1.0/]
Version 1.1: 18.1.2005 [
https://yaml.org/spec/1.1/]
Version 1.2: 10.1.2009 [
https://yaml.org/spec/1.2/spec.html]
Website
https://yaml.org
YAML-Parser für .NET
https://github.com/aaubry/YamlDotNet
Microsoft selbst liefert in
.NET Framework und
.NET Core noch keine YAML-Bibliothek mit. Diese Lücke füllt das Github-Projekt YamlDotNet [
https://github.com/aaubry/YamlDotNet]. Die kompilierte Bibliothek gibt es auf Nuget [
https://www.nuget.org/packages/YamlDotNet/]. Die erste dort veröffentlichte Version war 2013, seitdem sind zahlreiche Versionen erschienen. Die aktuelle Version zum Zeitpunkt der Erstellung des Beitrags ist 6.1.1 vom 4.6.2019. YamlDotNet basiert auf
.NET Standard 1.3, läuft daher in
.NET Core ab Version 1.0 und
.NET Framework ab Version 4.5 sowie
Mono und
Unity. Die Installation in einem Projekt erfolgt mit Install-Package YamlDotNet.
Bestandteile
Die wichtigsten Elemente in YAML sind:
Leerzeichen zur Einrückung als Strukturierungselement
Einfachen
Listen (alias Arrays);
Listenelemente beginnen mit einem Minuszeichen
Assoziativen
Listen (alias
Hashes, Maps, Dictionary) in der Form Name : Wert
Einzelwerten (Skalare): diese können, müssen aber nicht in einfachen oder doppelten Anführungszeichen stehen
Sprungmarken (Anker) und Verweise (Referenzen): die Sprungmarke beginnt mit dem kaufmännischen &, der Verweis darauf mit einem Stern *
Kommentaren (beginnen mit #)
Abschnitten (---), die ein Datei in mehrere Dokumente teilen können
Einsatzgebiete
YAML hat erst Mitte der 2010er-Jahre größere Bedeutung erhalten als es von
Docker als Konfigurationsformat für Deployment und
Debugging-Einstellungenverwendet wurde.
Microsoft verwendet YAML seit 2019 in
Azure DevOps.
Beispiel
Listing 1 zeigt ein
Objektmodell mit verschiedenen Datentypen (inkl.
Nullable Value Types),
Listen, einem Aufzählungstyp und einer zirkulären Referenzen. Der Programmcode ist eine komplexere Form eines Beispiels auf Github [
https://github.com/aaubry/YamlDotNet/blob/master/YamlDotNet.Samples/SerializeObjectGraph.cs]. Listing 2 zeigt die Serialisierung und
Deserialisierung mit YamlDotNet. Listing 3 zeigt das Ergebnisdokument.
Listing 1: Ein Objektmodell in C# mit zirkulären Referenzen
using System;
using
System.Collections.
Generic;
namespace ITVisions.Demo.BO
{
public enum Title
{
None, Dr, Prof, ProfDr
}
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
}
public class Order
{
public Guid Receipt
GUID { get; set; }
public DateTime Date { get; set; }
public Customer Customer { get; set; }
public List<Item> Items { get; set; }
public Address Bill_To { get; set; }
public Address Ship_To { get; set; }
public string SpecialDelivery { get; set; }
}
public class Customer
{
public string Name { get; set; }
public Employee Employee { get; set; }
}
public class Employee
{
public Title Title { get; set; }
public string Givenname { get; set; }
public string Surname { get; set; }
public DateTime? Birthday { get; set; }
public List<Receipt> Receipts { get; set; } = new List<Receipt>();
}
public class Item
{
public short Part_No { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
public int? Weight { get; set; }
}
}
Listing 2: Erzeugen eines Objektmodells und Serialisierung sowie Deserialisierung in YAML
using ITVisions.Demo.BO;
using System;
using System.Linq;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace ITVisions
{
public class YAMLDemo
{
public void Run()
{
Console.WriteLine("--- Creating Business Objects...");
var receipt = CreateBusinessObjects();
Console.WriteLine("--- Serializing...");
var serializer = new SerializerBuilder()
.WithNamingConvention(new PascalCaseNamingConvention())
.Build();
var yaml = serializer.Serialize(receipt);
Console.WriteLine("--- Result:");
Console.WriteLine(yaml);
Console.WriteLine("--- Deserializing...");
var deserializer = new DeserializerBuilder()
.WithNamingConvention(new PascalCaseNamingConvention())
.Build();
var receipt2 = deserializer.Deserialize<Order>(yaml);
Console.WriteLine("--- Result:");
ObjectDumper.Write(receipt2);
}
private static Order CreateBusinessObjects()
{
var address = new Address
{
Street = "De-La-Chevallerie-Straße 42,\nEtage 2",
City = "45894 Gelsenkirchen",
State = "NRW"
};
var receipt = new Order
{
Receipt
GUID = Guid.NewGuid(),
Date = DateTime.Now,
Customer = new Customer
{
Name = "5Minds IT Solutions Gmbh & Co KG",
Employee = new Employee
{
Title = Title.Dr,
Givenname = "Dr. Holger",
Surname = "Schwichtenberg"
}
},
Items = (new Item[]
{
new Item
{
Part_No = 123,
Description = "C# 7.3 Crashkurs",
Price = 14.99M,
Quantity = 40
},
new Item
{
Part_No = 456,
Description = "Moderne Datenzugriffslösungen mit \"Entity ramework Core 2.1/2.2
Ruby\"",
Price = 49.00M,
Quantity = 1
}
}).ToList(),
Bill_To = address,
Ship_To = address,
SpecialDelivery = "Bitte zusammen anliefern\n" +
"Wareneingang 2. Etage.\n" +
"Bitte am Empfang melden"
};
// recursion
receipt.Customer.Employee.Receipts.Add(receipt);
return receipt;
}
}
}
Listing 3: YAML-Dokument für das Objektmodell in Listing 1
&o0
Receipt
GUID: d5549070-102a-4768-8b65-03501b76af24
Date: 2019-06-12T20:16:55.2529275+02:00
Customer:
Name: 5Minds IT-Solutions Gmbh & Co KG
Employee:
Title: Dr
Givenname: Dr. Holger
Surname: Schwichtenberg
Receipts:
Items:
Description: C# 7.3 Crashkurs
Price: 14.99
Quantity: 40
Description: Moderne Datenzugriffslösungen mit "
Entity Framework Core 2.1/2.2
Ruby"
Price: 49.00
Quantity: 1
BillTo: &o1
Street: >-
De-La-Chevallerie-Straße 42,
Etage 2
City: 45894 Gelsenkirchen
State: NRW
ShipTo: *o1
SpecialDelivery: >-
Bitte zusammen anliefern
Wareneingang 2. Etage.
Bitte am Empfang melden