Technical Bulletin: Migrate HRIS Expressions from GoLang (GoTemplate) to EXPR

Overview

JumpCloud is transitioning its evaluation engine for Custom REST API Import Connectors from GoLang (GoTemplate) to EXPR. This upgrade introduces a more robust, expressive, and standardized expression language for attribute transformations, pre-processing filters, and user state management when importing identity records from external HRIS providers, like Workday, Personio, UKG Pro, and Dayforce.

Key Reasons for Migration

Enhanced Expressiveness: EXPR provides a purpose-built expression language with native operators, array manipulations, and string transformation capabilities that were cumbersome or limited in GoTemplates

Pre-Processing Data Filters: Enables complex filtering directly on incoming provider payloads—preventing state misalignment or unintended attribute overwrites when providers return multiple records per person (e.g., re-hires or multi-assignment profiles)

Dynamic Attribute & State Mappings: Simplifies translation logic for custom user attributes, dynamic group rules, and status mapping without requiring hardcoded translation lists

Admin Migration Workflow

  1. Notification: Administrators will receive an in-app notice when editing existing Custom REST API Import configurations that rely on GoTemplate expressions.
  2. In-App Migration Experience: JumpCloud will provide a guided migration interface within the console to help convert existing GoLang template rules into valid EXPR syntax.
  3. Verification: Admins should review and test converted expressions against sample API responses prior to saving the updated connector setup.

Note:

See the Official EXPR Documentation: EXPR Language Definition.

Writing EXPR Expressions

The following examples demonstrate how to construct an EXPR expression. Please note that providerUser. serves as the standard prefix for accessing any field provided by service providers

{
"id":"123"
"preferred_name":"xyz"
}

Expression: providerUser.preferred_name
Result: xyz

Expression: providerUser.preferred_name + " random string"
Result: xyz random str

{
"id": "123",
"username": "hello.world"
"preferred_name":"null"
}

Expression: (providerUser.preferred_name ?? "") != "" ? providerUser.preferred_name : providerUser.username

Result: hello.world

{
"id": "123",
"first_name": "Hello"
"last_name":"World"
}

Expression: providerUser.first_name + " " + providerUser.last_name
Result: Hello World

{
"id": "123",
"first_name": "Hello"
"last_name":"World"
"department":"Engineering"
"is_manager":true
}

Expression: providerUser.is_manager == true ? "Engineering Manager" : "Engineer"

Result: Engineering Manager

{
"id": "123",
"first_name": "John"
"last_name":"Doe"
"employement_type":{
"name":"IT Consultant
}
}

Expression: (providerUser.employment_type != nil && providerUser.employment_type.name != nil && providerUser.employment_type.name contains "Consultant" ? "[B2B] " : (providerUser.employment_type != nil && providerUser.employment_type.name != nil && providerUser.employment_type.name contains "Employee" ? "[EMP] " : "")) + (providerUser.first_name ?? "") + " " + (providerUser.last_name ?? "")

Result: [B2B] John Doe

{
"id": "123",
"eligible_paid_time_off": [
{ "policy_name": "Sick Policy",
"policy_uuid": "1b34bba6-ed31-4bfa-84a4-e70edae0d97d"
},
{
"policy_name": "Paid Time Off Policy",
"policy_uuid": "08fb23bc-88fb-484f-b805-aa7f22399575"
}
]
}

Expression: len(providerUser.eligible_paid_time_off ?? []) > 1 ? providerUser.eligible_paid_time_off[1].policy_name : ""

Result: Paid Time Off Policy

{ "id": "123",
"jobs": [
{ "compensations": [
{ "job_uuid": "53bee1b5-f7bc-4598-a5e1-66207cc73c4f",
"payment_unit": "Year",
"rate": "78000.00"
},
{
"job_uuid": "53bee1b5-f7bc-4598-a5e1-66207cc73c4f",
"payment_unit": "Year",
"rate": "85000.00"
}
]
}
]
}

Expression: len(providerUser.jobs ?? []) > 0 && len(providerUser.jobs[0].compensations ?? []) > 1 ? providerUser.jobs[0].compensations[1].rate : nil

Result: 85000.00

{
"customFieldGroup": {
"codeFields": [
{
"itemID": "13916651_182",
"nameCode": {
"codeValue": "T-Shirt Size",
"shortName": "T-Shirt Size"
}
},
{
"itemID": "1500091404_30",
"nameCode": {
"codeValue": "Uniform Size",
"shortName": "Uniform Size"
}
}
]
}
}

Expression: len(filter(providerUser.customFieldGroup.codeFields ?? [], #.itemID == "1500091404_30")) > 0 ? (filter(providerUser.customFieldGroup.codeFields ?? [], #.itemID == "1500091404_30")[0].nameCode?.codeValue ?? "") : ""

Result: Uniform Size

Migration Examples

GoLang Template ExpressionEXPR Expression

{{.preferred_name}}

providerUser.preferred_name

{{or .preferred_name .username}}

(providerUser.preferred_name ?? “”) != “” ? providerUser.preferred_name : (providerUser.username ?? “”)

{{.first_name}} {{.last_name}}

providerUser.first_name + ” ” + providerUser.last_name

{{- range .workAssignments -}}{{- if eq .assignmentStatus.statusCode.codeValue “A” -}}{{- if .assignedWorkLocations -}}{{- if (index .assignedWorkLocations 0).address -}}{{- (index .assignedWorkLocations 0).address.lineOne -}}{{- end -}}{{- end -}}{{- end -}}{{- end -}}

len(filter(providerUser.workAssignments ?? [], (#.assignmentStatus?.statusCode?.codeValue ?? ”) == ‘A’ && len(#.assignedWorkLocations ?? []) > 0)) > 0 ? (filter(providerUser.workAssignments ?? [], (#.assignmentStatus?.statusCode?.codeValue ?? ”) == ‘A’ && len(#.assignedWorkLocations ?? []) > 0)[0].assignedWorkLocations[0]?.address?.lineOne ?? ”) : ”

{{- range .workAssignments -}}{{- if eq .assignmentStatus.statusCode.codeValue “A” -}}{{- if .assignedWorkLocations -}}{{- if (index .assignedWorkLocations 0).address -}}{{- if (index .assignedWorkLocations 0).address.countrySubdivisionLevel1 -}}{{- (index .assignedWorkLocations 0).address.countrySubdivisionLevel1.shortName -}}{{- end -}}{{- end -}}{{- end -}}{{- end -}}{{- end -}}

len(filter(providerUser.workAssignments ?? [], (#.assignmentStatus?.statusCode?.codeValue ?? “”) == “A”)) > 0 && len(filter(providerUser.workAssignments ?? [], (#.assignmentStatus?.statusCode?.codeValue ?? “”) == “A”)[0].assignedWorkLocations ?? []) > 0 ? (filter(providerUser.workAssignments ?? [], (#.assignmentStatus?.statusCode?.codeValue ?? “”) == “A”)[0].assignedWorkLocations[0].address?.countrySubdivisionLevel1?.shortName ?? “”) : “”

{{ if or (and (.user.active) (eq .status “ACTIVE” “ACCEPTED”)) (and (not .user.active) (eq .status “TERMINATED” “INIT” “HIRED”)) }}{{ or .user.name.preferred_given_name .user.name.given_name }}{{ end }}

((providerUser.user?.active == true && providerUser.status in [“ACTIVE”, “ACCEPTED”]) || (providerUser.user?.active != true && providerUser.status in [“TERMINATED”, “INIT”, “HIRED”])) ? ((providerUser.user?.name?.preferred_given_name ?? “”) != “” ? providerUser.user?.name?.preferred_given_name : (providerUser.user?.name?.given_name ?? “”)) : nil
Back to Top

List IconIn this Article

Still Have Questions?

If you cannot find an answer to your question in our FAQ, you can always contact us.

Submit a Case