VAULOVAULO Help Center

JSON-Template mit Liquid-Syntax

Das JSON, das dein AssetFeed ausliefert, bestimmst du selbst: Ausgaben, Bedingungen und Schleifen in Liquid-Syntax, alle verfügbaren Variablen und die Funktionen für Text und Listen.

Jeder Listen-Endpunkt und jeder Einzel-Asset-Endpunkt im Modus Metadaten als JSON hat ein eigenes JSON-Template (Liquid). Du bearbeitest es im Dialog AssetFeed anpassen in einem Code-Editor mit Syntaxhervorhebung. Das Template ist ein JSON-Dokument, in das du mit der Liquid-Syntax Werte einsetzt, Bedingungen prüfst und über Listen läufst.

Beim Speichern prüft VAULO die Syntax des Templates. Ob alle verwendeten Funktionen existieren, zeigt sich erst beim Abruf: Ein Template mit einer unbekannten Funktion antwortet mit dem Statuscode 500. Öffne die Feed-URL deshalb nach jeder Änderung einmal im Browser.

Grundlagen

Zwei Schreibweisen reichen für fast alles:

  • {{ … }} gibt einen Wert aus, zum Beispiel {{ feed.title }}.
  • {% … %} steuert den Ablauf: Bedingungen, Schleifen, Variablen.
{
  "title": "{{ feed.title }}",
  "count": {{ page.totalItems }},
  "assets": [
    {% for asset in assets %}
    {
      "id": "{{ asset.id }}",
      "isImage": {% if asset.fileType == "Image" %}true{% else %}false{% endif %}
    }{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ]
}

Bedingungen

{% if asset.iptc.title %}"{{ asset.iptc.title }}"{% else %}null{% endif %}
{% if page.hasNext and page.index == 1 %} … {% endif %}
{% unless forloop.last %},{% endunless %}
{% if asset.fileType == "Video" %} … {% elsif asset.fileType == "Image" %} … {% else %} … {% endif %}

Vergleiche schreibst du mit ==, !=, <, <=, > und >=, verknüpft mit and und or. Ein Wert gilt als nicht erfüllt, wenn er fehlt oder null ist. Ein leerer Text "" gilt dagegen als erfüllt – prüfe Texte deshalb mit string.size oder ersetze sie mit object.default (siehe Funktionen).

Schleifen

{% for asset in assets %}
  {{ forloop.index }}   ← 0, 1, 2, … (beginnt bei 0)
  {{ forloop.first }}   ← true beim ersten Eintrag
  {{ forloop.last }}    ← true beim letzten Eintrag
{% endfor %}

{% for keyword in asset.iptc.keywords limit: 5 %} … {% endfor %}

Variablen, Kommentare und Rohtext

{% assign kind = asset.fileType %}
{% capture label %}{{ asset.filename }} ({{ kind }}){% endcapture %}
"label": "{{ label }}",

{% comment %} Wird nicht ausgegeben {% endcomment %}
{% raw %}{{ bleibt wörtlich stehen }}{% endraw %}

Mit {{- und -%} beziehungsweise {%- und -%} entfernst du Leerzeichen und Zeilenumbrüche rund um einen Tag.

Funktionen

Die klassischen Liquid-Filter wie | upcase, | date: "%Y" oder | default: "…" stehen nicht zur Verfügung. VAULO nutzt die Funktionen der Template-Engine Scriban: Der Name enthält einen Punkt, Argumente folgen durch Leerzeichen getrennt – ohne Doppelpunkt und ohne Komma.

{{ asset.filename | string.upcase }}                → LANDSCAPE10.JPG
{{ asset.filename | string.downcase }}              → landscape10.jpg
{{ asset.filename | string.slice 0 9 }}             → Landscape          (ab Position 0, 9 Zeichen)
{{ asset.iptc.description | string.truncate 20 }}   → Ein sehr langer B...
{{ asset.filename | string.replace ".jpg" "" }}     → Landscape10
{{ asset.filename | string.size }}                  → 15
{{ asset.filename | string.contains ".jpg" }}       → true
{{ asset.filename | string.split "." | array.last }} → jpg

{{ asset.iptc.keywords | array.join ", " }}         → Berlin, Sommer, Fest
{{ asset.iptc.keywords | array.size }}              → 3
{{ asset.iptc.keywords | array.first }}             → Berlin

{{ asset.iptc.title | object.default "Ohne Titel" }} → Ersatzwert, wenn der Wert fehlt oder leer ist

{{ asset.updatedAt | date.parse | date.to_string "%d.%m.%Y" }} → 09.09.2026

Funktionen lassen sich verketten: {{ asset.iptc.keywords | array.join ", " | string.upcase }}. Alles zu Datum und Uhrzeit steht unter Datum und Uhrzeit formatieren.

Variablen

feed

In jedem Template verfügbar.

VariableInhalt
feed.idDie ID des Feeds
feed.titleDer Titel des Feeds
feed.urlDie Feed-URL
feed.generatedAtZeitpunkt der Antwort, ISO 8601 in UTC

assets und asset

Ein Listen-Endpunkt erhält die Liste assets – eine Seite der veröffentlichten Dateien. Ein Einzel-Asset-Endpunkt im Modus Metadaten als JSON erhält die eine Datei als asset. Jedes Asset hat diese Felder:

VariableInhalt
asset.idDie ID der Datei
asset.assetIdDie Asset-ID der Datei aus dem Data Studio, zum Beispiel 000123. Leer, wenn der Datei noch keine Asset-ID zugewiesen ist – {% if asset.assetId %} prüft das
asset.filenameDateiname mit Endung
asset.contentTypeMIME-Typ, zum Beispiel image/jpeg
asset.fileTypeImage, Video, Audio, Pdf, MicrosoftOffice, Text, Markdown, Photoshop, Illustrator oder Unknown
asset.updatedAtLetzte Änderung, ISO 8601 in UTC
asset.urlTemporäre Direkt-URL auf die Datei in der angeforderten Größe
asset.iptcIPTC-Metadaten der aktiven Version (siehe unten)
asset.exifEXIF-Daten der Datei (siehe unten)
asset.tenantPropsBenutzerdefinierte Metadaten (siehe unten)

asset.iptc

Alle Felder sind Texte; fehlende Werte sind leer. asset.iptc.keywords ist eine Liste.

GruppeFelder
Beschreibungtitle, headline, description, descriptionWriter, keywords, personInImage
Ortcity, location, sublocation, state, country, countryCode
Urheber und Rechtecreator, creatorsJobTitle, copyrightNotice, credit, source, webStatementOfRights, rightsUsageTerms
VerwaltungsubjectCode, jobId, instructions, editStatus, category, supplementalCategories
Model und PropertymodelAge, additionalModelInformation, modelReleaseId, propertyReleaseId
KontaktcreatorContactExtendedAddress, creatorContactCity, creatorContactRegion, creatorContactPostalCode, creatorContactCountry, creatorContactWorkEmail, creatorContactWorkTelephone, creatorContactWorkUrl
BildlieferantimageSupplierId, imageSupplierName, imageSupplierImageId
Bildanalyseblurhash, dominantColor, isGrayscale (true oder false)

asset.exif

VariableInhalt
exif.dateTimeAufnahmezeitpunkt als ISO 8601 oder null
exif.fNumber, exif.exposureTime, exif.isoSpeedRatings, exif.focalLength, exif.orientationAufnahmewerte
exif.model, exif.lensModelKamera und Objektiv
exif.copyright, exif.colorProfile, exif.colorSpaceWeitere Texte
exif.gps.latitude, exif.gps.longitude, exif.gps.altitudeKoordinaten als Zahl oder null
exif.gps.timestampZeitstempel als ISO 8601 oder null
exif.gps.imgDirection, exif.gps.imgDirectionRef, exif.gps.mapDatum, exif.gps.processingMethod, exif.gps.hPositioningErrorWeitere GPS-Angaben

asset.tenantProps

Die Werte deiner benutzerdefinierten Metadaten aus dem Data Studio, ansprechbar über den Slug der Eigenschaft oder ihre Slot-ID, zum Beispiel asset.tenantProps.artikelnummer. Texte kommen als Text, Mehrfachauswahlen als Liste, Zahlen und Ja/Nein-Werte unverändert. Nicht gesetzte Eigenschaften sind leer.

page

Nur in Listen-Endpunkten.

VariableInhalt
page.indexAktuelle Seite, beginnend bei 1
page.sizeAssets pro Seite
page.totalItemsGesamtzahl der Assets im Feed
page.totalPagesAnzahl der Seiten
page.hasNexttrue, wenn es eine weitere Seite gibt
page.nextUrlURL der nächsten Seite oder null
page.previousUrlURL der vorherigen Seite oder null

Gültiges JSON erzeugen

Das externe System erwartet gültiges JSON. Diese Regeln helfen dir dabei:

  • Texte immer in Anführungszeichen setzen: "{{ asset.filename }}". Alle Textwerte sind bereits für JSON maskiert – Anführungszeichen oder Zeilenumbrüche im Bildtext machen dein JSON nicht kaputt.
  • Kommas in Schleifen: Nach dem letzten Eintrag darf kein Komma stehen. Schreibe {% unless forloop.last %},{% endunless %} hinter jedes Element.
  • Fehlende Werte: Leere Texte werden als "" ausgegeben. page.nextUrl, exif.dateTime und die GPS-Zahlen liefern null, wenn sie fehlen – du kannst sie ohne Anführungszeichen ausgeben oder mit {% if %} abfangen.
  • Listen ausgeben: Baue Arrays mit einer Schleife, zum Beispiel [{% for k in asset.iptc.keywords %}"{{ k }}"{% unless forloop.last %},{% endunless %}{% endfor %}].
  • Ergebnis prüfen: Öffne die Feed-URL im Browser und lass das Ergebnis von einem JSON-Validator prüfen, bevor das externe System darauf zugreift.

Beispiele

Standard-Template eines Listen-Endpunkts

{
  "version": 1,
  "id": "{{ feed.id }}",
  "title": "{{ feed.title }}",
  "generatedAt": "{{ feed.generatedAt }}",
  "nextPage": {% if page.nextUrl %}"{{ page.nextUrl }}"{% else %}null{% endif %},
  "assets": [
    {% for asset in assets %}
    {
      "id": "{{ asset.id }}",
      "filename": "{{ asset.filename }}",
      "contentType": "{{ asset.contentType }}",
      "type": "{{ asset.fileType }}",
      "updatedAt": "{{ asset.updatedAt }}",
      "url": "{{ asset.url }}"
    }{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ]
}

Standard-Template eines Einzel-Asset-Endpunkts

{
  "id": "{{ asset.id }}",
  "filename": "{{ asset.filename }}",
  "contentType": "{{ asset.contentType }}",
  "type": "{{ asset.fileType }}",
  "updatedAt": "{{ asset.updatedAt }}",
  "url": "{{ asset.url }}"
}

Erweitertes Beispiel mit Metadaten

{
  "feed": "{{ feed.title }}",
  "page": {
    "index": {{ page.index }},
    "total": {{ page.totalPages }},
    "next": {% if page.nextUrl %}"{{ page.nextUrl }}"{% else %}null{% endif %}
  },
  "items": [
    {% for asset in assets %}
    {
      "id": "{{ asset.id }}",
      "assetId": {% if asset.assetId %}"{{ asset.assetId }}"{% else %}null{% endif %},
      "name": "{{ asset.filename | string.replace ".jpg" "" }}",
      "title": "{{ asset.iptc.title | object.default asset.filename }}",
      "caption": "{{ asset.iptc.description | string.truncate 200 }}",
      "credit": "{{ asset.iptc.credit }}",
      "keywords": [{% for keyword in asset.iptc.keywords %}"{{ keyword }}"{% unless forloop.last %},{% endunless %}{% endfor %}],
      "articleNumber": "{{ asset.tenantProps.artikelnummer }}",
      "takenOn": {% if asset.exif.dateTime %}"{{ asset.exif.dateTime | date.parse | date.to_string "%Y-%m-%d" }}"{% else %}null{% endif %},
      "location": {
        "city": "{{ asset.iptc.city }}",
        "latitude": {{ asset.exif.gps.latitude }},
        "longitude": {{ asset.exif.gps.longitude }}
      },
      "image": "{{ asset.url }}",
      "permalink": "{{ feed.url }}/assets/{{ asset.filename }}"
    }{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ]
}

On this page