Zum Inhalt

Welche Sprache wo?

Pantarey wertet an vielen Stellen Ausdrücke aus: im Prozess Designer, im Daten Designer, in Formularen, Dashboards und in der Datenanalyse. Dahinter stehen fünf Mechaniken, die sich in Schreibweise und Verhalten unterscheiden. Die meisten Fehler entstehen, wenn ein Feld in der einen Sprache beschrieben wird, aber eine andere erwartet. Diese Seite ist die Landkarte: welches Feld welche Sprache erwartet, was $ oder der Kontext dort bedeutet und wie ein typischer Ausdruck aussieht. Die einzelnen Sprachen haben eigene Seiten: JSONata in Pantarey, Template-Funktionen $fn, Handlebars-Helfer.

Die fünf Mechaniken

JSONata. Das ganze Feld ist ein Ausdruck, der aus der Nachricht oder dem Datensatz ein Ergebnis berechnet: ein Feld, ein neues Objekt, eine gefilterte Liste. Ein leeres Feld lässt die Daten unverändert; ein Ausdruck ohne Ergebnis ist ein Fehler. Felder stehen ohne Klammern: antrag_db.mitarbeiter.

Platzhalter $(pfad) mit $fn(…). In Textfeldern wie Vorgangskennung, Betreff oder Dateiname wird jeder Platzhalter durch den Wert des Pfads ersetzt, der Rest des Texts bleibt stehen. Funktionen wie $fn('str_upper', $(name)) formen den Wert um; ein fehlender Wert ergibt leeren Text.

JavaScript. Gateway-Bedingungen, berechnete Felder und Prüfregeln mit Sprache JavaScript sowie Formular-Bedingungen werden als JavaScript ausgewertet. Am Gateway werden zuerst die $(…)-Platzhalter ersetzt, dann läuft der Vergleich; im Daten Designer stehen $, obj und root für den Datensatz.

Handlebars. HTML- und Textvorlagen für PDF, E-Mail und externe Aufgaben verwenden {{feld}}-Blöcke mit einem zentralen Satz von Helfern. Der Kontext ist das Ergebnis des zugehörigen Daten-Mappings, ohne Mapping die ganze Eingabe der Aktivität.

SQL. Abfragen im Datenbank-Element, die Live-Daten der externen Aufgabe, das Formularfeld Werte laden, die Datenanalyse und SQL-Widgets sind SQL (Athena/Trino). Platzhalter $(…) und $fn('sql_list', …) gibt es nur im Datenbank-Element und in den Live-Daten; Formular und Analyse kennen stattdessen Systemplatzhalter wie @currentUserEmail.

Quer durch alle Mechaniken gehen zwei Token: {{value:name}} setzt einen Wert ein und wird vor allem anderen ersetzt, aber nur in Designer-Texten, nie in Formular- oder Datensatzdaten. {{secret:NAME}} setzt ein Secret ein und wirkt ausschließlich in den Eingaben von Service-Aufgaben an dafür freigegebenen Pfaden, etwa headers.Authorization beim HTTP-Aufruf.

Erkennungsregel

Ob ein Feld JSONata oder Platzhalter erwartet, verrät sein Label: Felder mit dem Zusatz (JSONata) nehmen einen ganzen Ausdruck, alle anderen Textfelder nehmen Text mit $(…)-Platzhaltern.

Erkennung Sprache Feld lesen Beispiel
Ganzes Feld ist ein Ausdruck JSONata feld, $.feld, $$.feld antrag_db.mitarbeiter
Platzhalter im Text $(pfad) + $fn $(feld), $($$context.feld) Urlaub $(antrag_db.von) prüfen
Vergleich am Gateway JavaScript nach $(…) $(feld) $(pruefung.ok) === false
{{…}} in einer Vorlage Handlebars {{feld}} {{currency_eur betrag}}
select … from … SQL Spaltennamen, in der Datenbank '$(feld)' select id from invoices where kunde = '$(kunde)'

Ort in der App

Die Tabelle nennt die Felder mit ihrer Bezeichnung in der Oberfläche. „Nachricht“ ist das JSON, das durch den Prozess wandert, siehe Daten im Prozess; „Eingabe“ ist die Nachricht nach dem Input-Ausdruck der Aktivität.

Prozess Designer: Aufgaben, Daten & Variablen

Ort in der App Sprache Was $ bzw. der Kontext ist Beispiel
Daten & Variablen konfigurieren → Input-Ausdruck (JSONata) JSONata $ = aktuelle Nachricht, $$ = Wurzel der Nachricht; $fn(…) verfügbar, {{value:…}} vorher eingesetzt { "to": antrag_db.mitarbeiter, "von": $fn('date_toGermanDate', antrag_db.von) }
Daten & Variablen konfigurieren → Output-Ausdruck (JSONata) JSONata $ = Rohergebnis der Aktivität payload.body.pdf
Daten & Variablen konfigurieren → Ergebnispfad Pfad (Kleinbuchstaben, Unterstrich, Punkte) + $(…) Platzhalter werden gegen das Ergebnis des Schritts aufgelöst, nicht gegen die Nachricht; __proto__, constructor, prototype sind verboten ergebnis_$(schritt)
Eigenschaften → Technisch → Vorgangskennung $(pfad) + $fn(…) aktuelle Nachricht beim Erreichen des Elements; in Schleifen je Durchlauf das aktuelle Element RE-$(rechnung_db.prio_seq) $fn('str_upper', $(kunde.name))
Benutzeraufgabe → Anzeigetext $(pfad) + $fn(…) wie Vorgangskennung Rechnung $(rechnung_db.prio_seq) prüfen
Benutzeraufgabe → Zuweisung („Wer soll die Aufgabe durchführen?“) $(pfad) + $fn(…) wie Vorgangskennung $($$context.executedBy)
Benutzeraufgabe → Benutzerdefiniertes Formular, Formular (erweitert) erst $(…)-Ersetzung, dann JSONata das Formular-JSON ist ein JSONata-Ausdruck über die Nachricht; Ergebnis muss die Feldliste sein [ { "template": request_summary.html }, { "key": "begruendung", "type": "input" } ]
Benutzeraufgabe → Zeitlimit Datum aus Prozessdaten $(pfad) ISO-Datum oder Sekunden aus der Nachricht $(deadline)
Zwischenereignis Timer → Wartezeit (Sekunden) $(pfad) Ergebnis wird als Zahl gelesen $(wartezeit)
Signal werfen → Nutzdaten, Signalname $(pfad) im JSON-Text gegen die Nachricht; das Ergebnis muss gültiges JSON bleiben { "orderId": "$(orderId)" }

Startereignisse

Ort in der App Sprache Was $ bzw. der Kontext ist Beispiel
Startereignis (Zeitplan, einfaches Startereignis) → Input-Ausdruck (JSONata) JSONata $ = Startnachricht, beim Timer nur { "$$context": … }. Beim Benutzer-Start wird der Input-Ausdruck übersprungen; die Formulardaten werden unverändert zur Nachricht { "stichtag": $substring($now(), 0, 10) }

Input und Ergebnis des Startereignisses sind auf je 50 KB Text begrenzt; die Validierung meldet sonst „Start Event Nachricht überschreitet Größenlimit (max. 50 KB)“. Mehr zu den Startarten unter Startereignisse.

Gateway

Ort in der App Sprache Was $ bzw. der Kontext ist Beispiel
Sequenzfluss am XOR-Gateway → condition expression JavaScript nach $(…)-Ersetzung Textwerte werden automatisch in "…" gesetzt (außer der Platzhalter steht schon in Anführungszeichen), fehlende Werte werden zu undefined, null bleibt null, Objekte werden JSON; {{value:…}} typgerecht; kein $, kein $$, kein JSONata $(pruefung.ok) === false, $(manager_approval.$$context.selectedAction) === 'approve', $(betrag) > {{value:schwelle}}
Gateway → Default Flow – Flows ohne Bedingung (außer dem Default) sind ein Fehler („Ausgehende Flows ohne Bedingung gefunden“); treffen alle Bedingungen nicht zu und es gibt keinen Default, scheitert der Schritt („Kein Default-Pfad definiert …“); der erste zutreffende Flow in Modellreihenfolge gewinnt

Die Regeln für Bedingungen stehen unter Gateway und Bedingungen.

Datenbank-Element

Ort in der App Sprache Was $ bzw. der Kontext ist Beispiel
Datenbank-Element (eingehend) → Input, Operationen Write, Update, Merge JSONata, danach $(…)-Ersetzung über den JSON-Text des Ergebnisses JSONata gegen die Nachricht; $(…) in Textwerten des Schreibobjekts werden danach noch ersetzt $sift(vacation_user_entry, function($v, $k) { $k != '$$context' })
Datenbank-Element Delete → Objekt-ID $(pfad) gegen die Nachricht $(antrag_db.id)
Datenbank-Element Read → Object id $(pfad) muss nach der Ersetzung eine 26-stellige ULID sein, sonst „Ungültige ID angegeben“ $(kunde.id)
Datenbank-Element Read → Object prefix $(pfad) Präfix des Dokumentnamens 2026/$(monat)
Datenbank-Element Read → Abfrage SQL mit $(pfad), $fn('sql_list', …), $fn('sql_raw', …) Textwerte gehören in '…'; außerhalb von Anführungszeichen sind nur Zahlen, true, false und null erlaubt; ein Wert mit ' wird gemeldet select id from invoices where kunde IN ($fn('sql_list', $(kunden)))
Datenbank-Element Read → Output, Ergebnispfad JSONata, Pfad $ = gelesenes Objekt bzw. Liste $[0]

Service-Aufgaben: PDF, E-Mail, Graustufen, Handlebars

Ort in der App Sprache Was $ bzw. der Kontext ist Beispiel
E-Mail versenden an externe Empfänger → Betreff $(pfad) + $fn(…), einzeilig gegen die Eingabe der Aktivität Rechnung $(rechnung.nummer)
E-Mail → Empfänger (An, Cc, Bcc), Absender-E-Mail, Antwort an JSONata, Adressen als Text toleriert JSONata gegen die Eingabe; sieht der Text wie eine Adresse oder Adressliste aus (a@b.de, Name <a@b.de>, Komma, Semikolon, Zeilenumbruch), gilt er wörtlich kunde.email, info@firma.de, [antrag_db.mitarbeiter, "chef@firma.de"]
E-Mail → Anhänge JSONata Ergebnis sind Dateiverweise { "referenceId": …, "filename": …, "contentType": … }; alles ohne referenceId wird verworfen invoice.pdfReference, [rechnung_pdf, anlage]
E-Mail → HTML-Dateninput (JSONata) JSONata leer → die ganze Eingabe ist Handlebars-Kontext { "customer": customer, "items": positions }
E-Mail → HTML-Inhalt Handlebars Kontext = Ergebnis des HTML-Dateninputs; {{value:…}} wird erst hier eingesetzt {{currency_eur betrag}}
PDF erstellen aus Template → Daten (JSONata) JSONata $ = Eingabe der Aktivität $.invoice
PDF → PDF Template (HTML + Handlebars) Handlebars Kontext = Ergebnis von Daten (JSONata), leer → ganze Eingabe {{kunde.name}}
PDF → Dateiname $(pfad) + $fn(…) gegen die ganze Eingabe, unabhängig vom Daten-Mapping; / wird -; leer = document.pdf; der erweiterte Editor ist hier aus Rechnung_$(invoiceNumber).pdf
PDF in Graustufen umwandeln → Eingabe-Datei (JSONata) JSONata muss ein Datei-Objekt mit referenceId liefern; Standard $.document attachment, files[0]
Text aus Vorlage erstellen (Handlebars) Handlebars; Eingabe per Input-Ausdruck { content, template } content ist der Kontext, template die Vorlage { "content": $, "template": "Hallo {{name}}" }
E-Mail aus Vorlage (SMTP, Microsoft 365, interne Vorlage) Handlebars Kontext = contentData; SMTP rendert HTML, Betreff und Text, Microsoft 365 nur den Inhalt (Betreff nicht), die interne Vorlage Inhalt und Betreff

Externe Aufgabe

Ort in der App Sprache Was $ bzw. der Kontext ist Beispiel
Externe Aufgabe → HTML-Seite, Betreff, E-Mail-Text, Teams-Text, Seiten „Bereits beantwortet“, „Erfolg“, „Abgelaufen“, „Abgebrochen“, Erfolgsseite je Aktion Handlebars, gleicher Helfer-Satz wie PDF und E-Mail Kontext = data der Eingabe (Standard-Input { "data": $ }), sonst die ganze Eingabe; dazu die Marker %%EXTERNAL_URL%%, %%FILE:var%% und <button data-action="…">, die kein Handlebars sind {{name}}
Externe Aufgabe → Benachrichtigung: Empfänger, Cc, Bcc, Absenderadresse $(pfad) data und Wurzel der Eingabe gemischt, bei gleichen Namen gewinnt die Wurzel max@firma.de, $(email)
Externe Aufgabe → Live-Daten SQL-Abfrage SQL mit $(…) und $fn('sql_list', …) gegen data; einmal beim Anlegen der Aufgabe ausgeführt, Ergebnis in der Seite als window.__liveData select * from auftrag where id = '$(auftrag_id)'

Daten Designer

Ort in der App Sprache Was $ bzw. der Kontext ist Beispiel
Attribut → Reiter Berechnet → Sprache JSONata oder JS, siehe Berechnete Felder JSONata oder JavaScript JSONata: $ = Datensatz bzw. Listenzeile, $root = ganzer Datensatz, $old = gespeicherter Vorzustand (null bei Neuanlage). JS: $, obj, root, $old $sum(positionen.(menge * preis)), $old.status != status ? $now() : $old.status_seit
Reiter Validierung → Sprache, Ausdruck, Fehlermeldung, siehe Prüfregeln JSONata oder JavaScript; Fehlermeldung mit $(feldname) JSONata: $ und $root = Datensatz, kein $old; JS: $, obj, root = Datensatz; Regel erfüllt = wahr bis >= von; „Bis $(bis) darf nicht vor Von $(von) liegen.“
Attribut → Reiter Bedingungen (Pflichtfeld, ausblenden, deaktivieren), siehe Dynamische Formulare JavaScript im Browser data (ganzer Datensatz), model (Elternobjekt, in Listen die Zeile), field, formControl, value, loaded (Werte aus Werte laden) model.status === 'abgelehnt'
Attribut → Ersatzwert $(pfad) + $fn(…) gegen den Datensatz beim Speichern, nur wenn das Feld leer ist $fn('nextId', 'kunde')
Dokumentenname, Dokumentennamen-Baukasten, siehe Dokumentname $(pfad) + $fn(…) gegen den Datensatz; Wertelisten-Werte sind vorher durch ihre Beschriftung ersetzt; / im Wert wird -, / in der Vorlage bildet Ordner; Ergebnis wird auf 500 Zeichen gekürzt $fn('date_toPath', $(datum))/R-$fn('str_padStart', $(prio_seq), 5, '0')

Formular: Werte laden

Ort in der App Sprache Was $ bzw. der Kontext ist Beispiel
Formularfeld Werte laden (sql-values), siehe Formulare SQL mit Systemplatzhaltern @currentUserEmail, @currentDate, @currentYear keine $(…)-Platzhalter, keine Formularwerte; Ergebnis liegt unter loaded.<key> im Formularzustand, nicht im Datensatz SELECT CAST(work_days AS JSON) AS work_days FROM employees WHERE lower(e_mail) = lower('@currentUserEmail')

Dashboards

Ort in der App Sprache Was $ bzw. der Kontext ist Beispiel
Widget Datensatz → Datensatz-Anzeige konfigurieren → JSONata-Ausdruck JSONata im Browser, ohne $fn und andere Pantarey-Funktionen gegen die Nachricht des Kanals, root = Nachricht; Ergebnis ist ein Objekt oder eine ID, leer oder null lässt den aktuellen Datensatz stehen; Ausdruck testen mit Beispiel-Nachricht (JSON) rechnungsempfaenger
Widget Planungstafel → Absicht → Bedingung und Texte Bedingung: JSONata im Browser; Texte: $(entry.x), $(row.x), $(range.start), $(user.email), $(choice) Kontext { entry, row, range, user }, entry und row enthalten Daten und Metafelder gemischt; true bietet die Aktion an, false oder kein Ergebnis verbirgt sie, ein Text zeigt sie deaktiviert mit diesem Grund entry.status = 'geplant'

Datenanalyse

Ort in der App Sprache Was $ bzw. der Kontext ist Beispiel
Datenanalyse, SQL in Widgets SQL Systemplatzhalter @currentUserEmail, @currentDate; keine $(…)-Platzhalter

Die häufigsten Verwechslungen

  • $(feld) in einem JSONata-Feld. Im Input- oder Output-Ausdruck ist $(…) ein Funktionsaufruf und scheitert. In JSONata steht das Feld ohne Klammern: feld oder $.feld.
  • JSONata im Betreff. Der Betreff ist Text mit Platzhaltern. rechnung.nummer bleibt dort wörtlich stehen; richtig ist Rechnung $(rechnung.nummer).
  • {{secret:NAME}} im Formular oder in einer Benutzeraufgabe. Der Token bleibt als Text stehen. Secrets wirken nur in den Eingaben von Service-Aufgaben an freigegebenen Pfaden, siehe Secrets.
  • $fn('sql_list', …) in JSONata. Die Meldung lautet „fn(): not allowed in jsonata: 'sql_list'“. sql_list und sql_raw gehören in SQL-Abfragen mit $(…); in JSONata wird eine Liste direkt gebaut.
  • / wird zu -. Bei jedem $(…)-Platzhalter wird ein Schrägstrich im Wert zum Bindestrich, nicht nur im Dokumentnamen, sondern auch im Betreff, in der Vorgangskennung und im Dateinamen. Ausnahme: Gateway-Bedingungen.
  • Das Gateway kennt kein $. Eine Bedingung ist JavaScript; $, $$ und JSONata-Funktionen gibt es dort nicht. $$context ist nur innerhalb eines Platzhalters erreichbar: $(aufgabe.$$context.selectedAction) === 'approve'.

Regeln der Platzhalter

  • Ein Platzhalter ist $(pfad); im Pfad sind Buchstaben, Ziffern, _, ., $, -, @, # und % erlaubt, deshalb geht $($$context.executedBy).
  • Ein fehlendes Feld oder null ergibt leeren Text. Zahlen und Wahrheitswerte werden Text, Objekte und Listen werden JSON, / in Textwerten wird -. Die Pfadteile __proto__, constructor und prototype ergeben immer leeren Text.
  • Reihenfolge: zuerst das innerste $fn(…), dann $(…) und die alten Schreibweisen $nextCounter(…), $ulid(), $dateToPath(…), $toGermanDate(…), zuletzt $fn noch einmal. Klammern und Kommas in Textargumenten gehören in '…'.
  • Argumente von $fn mit $ kommen als Text an („0815“ bleibt „0815“); Literale ohne $ werden umgewandelt (5 wird Zahl, true, false, null; '5' bleibt Text).
  • Längen: Vorgangskennung 500, Anzeigetext 300, Zuweisung 200, Ergebnispfad 1000 Zeichen. Wird eine Grenze überschritten, scheitert der Schritt mit FIELD_LENGTH_EXCEEDED. Der Dokumentname wird bei 500 Zeichen gekürzt statt abgelehnt.
  • Am Gateway gelten andere Regeln: Textwerte werden in "…" gesetzt, fehlende Werte werden undefined, / bleibt /.

Werte und Secrets

{{value:name}} wird in allen Designer-Texten ersetzt, in Code-Feldern typgerecht (ein Objekt-Wert bleibt Objekt, ein Text in JSONata wird zu "…"), in Textfeldern als Text. Der Deploy prüft unbekannte Namen. In PDF- und E-Mail-HTML-Vorlagen wird der Wert erst beim Rendern eingesetzt. Alles dazu unter Werte im Prozess.

{{secret:NAME}} ersetzt Pantarey nur in Service-Aufgaben an den Pfaden, die der jeweilige Service freigibt, etwa URL und Autorisierungs-Header beim HTTP-Aufruf, Zugangsdaten bei SMTP, Microsoft 365, FTP, SharePoint, Teams oder E-POST. Außerhalb davon bleibt der Token stehen. Alles dazu unter Secrets.

Beispiel

Im Prozess „Urlaub beantragen“ der Musterfirma GmbH schreibt „Antrag speichern“ den Datensatz mit dem Input $sift($, function($v, $k) { $k != '$$context' }) (JSONata) und dem Ergebnispfad antrag_db. Die Benutzeraufgabe „Urlaubsantrag genehmigen“ hat den Anzeigetext Urlaub $(antrag_db.mitarbeiter) vom $fn('date_toGermanDate', $(antrag_db.von)) (Platzhalter). Das Gateway dahinter prüft $(entscheidung.$$context.selectedAction) === 'approve' (JavaScript). „Zusage senden“ baut die E-Mail mit dem Input-Ausdruck (JSONata), der Betreff lautet Urlaub genehmigt: $(antrag_db.von) (Platzhalter), der HTML-Inhalt nutzt {{von}} (Handlebars).

Häufige Fragen

Woran erkenne ich, ob ein Feld JSONata oder Platzhalter erwartet?

Am Label. Steht dort (JSONata), ist das ganze Feld ein Ausdruck und ein Feld wird ohne Klammern angesprochen. Sonst ist es ein Textfeld, in dem nur $(…)-Platzhalter ersetzt werden.

Warum steht im Betreff mein Ausdruck wörtlich drin?

Der Betreff nimmt Platzhalter, kein JSONata. kunde.name bleibt Text; $(kunde.name) wird ersetzt.

Kann ein Platzhalter auf $$context zugreifen?

Ja, mit $($$context.executedBy) für den letzten Schritt oder $(aufgabe.$$context.selectedAction), wenn das Ergebnis der Aufgabe unter aufgabe liegt.

Funktionieren $fn-Funktionen im Dashboard?

Nein. Das Datensatz-Widget und die Planungstafel werten JSONata im Browser aus, ohne Pantarey-Funktionen. Dort gilt nur die JSONata-Standardbibliothek.

Warum ändert sich mein Ordner-Trennzeichen im Betreff?

Platzhalter wandeln / in Textwerten immer in - um. Soll ein Ordner im Dokumentnamen entstehen, gehört der / in die Vorlage, nicht in den Wert.

Nächster Schritt

JSONata in Pantarey: Variablen, $$context, zehn Grundmuster, Fehlerverhalten und Testen mit der Live-Vorschau.