Daten-Mapping mit der JSON-Mapping-Language

Import und Exporter beliebiger CSV-, XML- oder JSON-Daten

Wer kennt das Problem nicht? In ein neues oder bestehendes, datenzentriertes Projekt müssen verschiedene Datenquellen angebunden werden. Wenn man Glück hat, stehen moderne APIs der Drittsysteme zur Verfügung, die JSON oder XML ausliefern. Oftmals aber sind lediglich flache CSV-Listen vorhanden, die aufwendig in die bestehende Datenstrukturen übernommen werden müssen.

Aber egal ob CSV, XML oder JSON, der Aufwand ist immer der gleiche. Beim Import muss manuell das Quellformat analysiert und aufwendig programmatisch in die eigene Datenstruktur überführt werden. In die andere Richtung genau das gleiche Spiel. Und genau diesen manuellen Programmieraufwand übernimmt im  neuen Contentfly CMS das Mapping-Plugin. Über die Contentfly JSON-Mapping-Language (JMAL) können beliebige Datenstrukturen auf die Entitäten gemappt werden. Für jede Mapping-Definition stehen daraufhin automatisiert Import- und Exportfunktionen, sowohl über die Konsole, die API, als auch über die Benutzerüberfläche im Backend zur Verfügung.

Einfaches CSV-Mapping

Als einfaches Beispiel sehen wir uns folgende CSV-Datei an, deren Spalten in die Entität "Produkt" gemappt werden sollen.

name;beschreibung;baujahr;ps;kat;kategorie
A4;Neuer A4;2018;260;ok;Kombi
A3;Gebrauchter Jahreswagen;2016;220;ok;Cabrio
A-Klasse;Altes Modell;2001;160;;Limousine

In JMAL wird dieses einfache Mapping wie folgt definiert:

{
   "#TITLE": "CSV-Mapping Autos",
   "#TYPE": "csv",
   "#MAP": {
      "#ENTITY: "Produkt",
      "#ID": "name",
      "#CLEAN": false,
      "#COLS": {
         "0": "name",
         "1": "beschreibung",
         "2": "baujahr",
         "3": "ps",
      }
   }
}

Über #TITLE ist der Import/Export später in der Benutzeroberfläche des Backends abrufbar, als #TYPE stehen csv, xml oder json zur Verfügung. Das eigentliche Mapping wird in #MAP gespeichert. Zuerst wird die Basis-Entität über #ENTITTY zugeordnet. Über den optionalen Token #ID wird ein eindeutiges Feld (oder auch mehrere per Komma getrennt) definiert. Wenn in diesem Beispiel das Auto mit dem Namen "A4" bereits besteht, wird es lediglich aktualisiert, ansonsten neu angelegt. Der ebenfalls optionale Token #CLEAN gibt an, ob die Datenbanktabelle/Entität vor dem Import geleert werden soll (SQL: DELETE FROM). Unter #COLS wird die eigentliche Zuordnung von Spalte zu Eigenschaft/Datenbankfeld definiert. In diesem Beispiel sollte die Zuordnung einfach ersichtlich sein.

Registriert wird das Mapping über folgenden Eintrag in der custom/app.php

$app['pluginManager']->register('Areanet_Mapping');
$app['mappingManager']->add('products', '../pfad/zur/mapping-datei.json');

Im Anschluss kann - ohne weitere Programmierung - diese CSV-Datei automatisiert über die Konsole importiert werden:

php appcms/console.php contentfly:import products ../pfad/zur/import-datei.csv

Ein etwas umfangreicheres Beispiel in JMAL mit Joins und Co

Im obigen Beispiel haben wir lediglich die ersten 4 Spalten verwendet. Im nächsten Schritt wollen wir zusätzlich die 4. Spalte (die Spalten beginnen bei der Zählung mit o) auf die Eigenschaft "katVorhanden" (Boolean-Value) mappen. Wenn der Text "ok" vorkommt, soll die Eigenschaft "true" sein, ansonsten "false". Die 5. Spalte soll auf die Eigenschaft "kategorie" gemappt werden, die wiederum eine ManyToOne-Verknüpfung zur Entität "Kategorie" (mit einer Eigenschaft "name") darstellt. In "Produkt.kategorie" soll also nicht der Name der Kategorie, sondern die ID der Kategorie gespeichert werden.

Kommt jetzt  JMAL an die Grenzen? Natürlich nicht:

{
   "#TITLE": "CSV-Mapping Autos",
   "#TYPE": "csv",
   "#MAP": {
      "#ENTITY: "Produkt",
      "#ID": "name",
      "#CLEAN": false,
      "#COLS": {
         ...
         "4": {
            "#PROPERTY": "katVorhanden",
            "#TYPE": "switch",
            "#DEFAULT": false,
            "#CASE":{
               "ok":true
            }
         }
         "5": {
            "#PROPERTY": "kategorie",
            "#TYPE": "join",
            "#ENTITY": "Kategorie",
            "#ID": "name",
            "#COLS":{
               "5":"name"
            }
         }
      }
   }
}

Und das war natürlich nicht alles. Die Contentfly JSON-Mapping-Language kommt auch mit mehrfach verschachtelten Joins oder MultiJoins (ManyToMany) klar - ohne eine Zeile Import-Code schreiben zu müssen. Und die gleiche Sprachsyntax kann auch auf XML- oder JSON-Dateien angewendet werden. Damit wird die flexible Anbindung beliebiger Datenquellen an das Contentfly CMS weiter vereinfacht.

Stay tuned!

zurück zur Übersicht