YAML/JSON Reportgenerator mit EasyGen

Yaml und JSON sind wunderbare Datenformate für viele Arten von Datenmodellen, nur wie bekommt man diese Daten mal eben schnell in andere Formate wie CSV, LaTex oder HTML konvertiert, ohne dafür einen eigenen Konverter programmieren zu müssen?

EasyGen bietet sich da als Lösung an. EasyGen lädt das Datenmodell direkt aus einer JSON oder Yaml- Datei und verwendet dann die Go Template Engine, um ein Template aus einer Template- Datei mit den Werten aus dem Modell zu füllen.

Zugegebermaßen erfordert der Umgang mit der richtigen Syntax im Tepmplate etwas Lernschmerz und Übung, bis man ein Gefühl dafür bekommt, wo man sich gerade im Modell aufhält und wo genau gerade eigentlich der aktuelle Key und sein Wert zu finden ist, den man dann ja wieder für die nächste darunterliegende Iterationsschleife braucht.

Am Ende jedoch ist das Template viel kürzer und mit etwas Übung und Copy & Paste aus existierenden Macros dann schneller gemacht, als erst ein eigenes Programm zu frickeln, was die Daten konvertiert.

Hat man z.B. eine Liste von hinterlegten Requirements

result.json
{
    "mymodule": {
        "obj": {
            "requirements": [
                {
                    "sev": "5",
                    "text": [
                        "\n",
                        "Lorem ipsum dolor sit amet, consetetur sadipscing elitr,",
                        "\n",
                        "sed diam nonumy eirmod tempor invidunt ut labore et dolore",
                        "\n",
                        "magna aliquyam erat, sed diam voluptua."
                    ]
                },
                {
                    "sev": "6",
                    "text": [
                        "\n",
                        "At vero eos et accusam et",
                        "\n",
                        "justo duo dolores et ea rebum. Stet clita kasd gubergren,",
                        "\n",
                        "no sea takimata sanctus est Lorem ipsum dolor sit amet."
                    ]
                }
            ]
        }
    }
}

und ein kleines Template

Requirements.tmpl
{{- range $elementName, $data := . -}}
    {{- range .obj.requirements }}
Modul:{{ $elementName}}
Severity: {{ .sev}}
        {{range .text -}}
        {{- . -}}
        {{- end}}
    {{ end -}}
{{- end -}}

Dann erzeugt dies eine Ausgabe der Inhalte, den man dann natürlich noch weiter aufpeppen könnte, um damit z.B. LaTex zu füttern.

Modul:mymodule
Severity: 5

Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore
magna aliquyam erat, sed diam voluptua.

Modul:mymodule
Severity: 6

At vero eos et accusam et
justo duo dolores et ea rebum. Stet clita kasd gubergren,
no sea takimata sanctus est Lorem ipsum dolor sit amet.

Hier noch ein großes Beispiel, welches CanDB- Informationen in eine HTML- Tabelle konvertiert. Man sieht auch, wie Werte einer oberen Ebene in einer Variablen gespeichert werden (z.B. $element), um dann in einer unteren Ebene dann ausgegeben zu werden

CanMessages.tmpl
{{- range $name, $data := . -}}
    {{- $element := $name -}}
    {{- $nodeName := .obj.candb.node_name -}}
    {{- range $name, $values := .obj.candb -}}
        {{- if eq $name "messages" -}}
        <h2>{{ $name -}}</h2>
<table>
<tr>
<th>element</th>
<th>nodeName</th>
<th>messagename</th>
<th>length</th>
<th>messageid</th>
<th>signalname</th>
<th>name</th>
<th>bitlength</th>
<th>bitstart</th>
<th>endian</th>
<th>max</th>
<th>min</th>
<th>name</th>
<th>offset</th>
<th>scale</th>
<th>unit</th>
</tr>
            {{- range $messageid, $messageStructs := $values -}}
             {{- $length :=$messageStructs.length -}}
             {{- $messagename :=$messageStructs.name -}}
                {{- range $signalname, $signalvalues := $messageStructs -}}
                    {{- if eq $signalname "signals" -}}
                        {{- range $signalvalues -}}
                            <tr>
                            <td>{{$element -}}:</td>
                            <td>{{- $nodeName -}}:</td>
                            <td>{{- $messagename -}}:</td>
                            <td>{{- $length -}}:</td>
                            <td>{{- $messageid -}}:</td>
                            <td>{{- $signalname -}}:</td>
                            <td>{{- .name}}</td>
                            <td>{{- .bitlength -}}:</td>
                            <td>{{- .bitstart -}}:</td>
                            <td>{{- .endian -}}:</td>
                            <td>{{- .max -}}:</td>
                            <td>{{- .min -}}:</td>
                            <td>{{- .name -}}:</td>
                            <td>{{- .offset -}}:</td>
                            <td>{{- .scale -}}:</td>
                            <td>{{- .unit -}}:</td>
                            <tr>
                        {{ end -}}
                    {{- end -}}
                {{- end -}}
            {{- end -}}
            </table>
        {{- end -}}
    {{- end -}}
{{- end -}}