Transform Basics
Transforms use Go's text/template syntax to restructure JSON data. Here's a simple example:
{
"user": {
"name": "{{.name}}",
"id": "{{.id}}",
"email": "{{.email}}"
}
}
The transform above extracts fields from the input and places them in a new structure.
Template Variables
Use dot notation to access fields from the input data:
"name": "{{.user.profile.firstName}} {{.user.profile.lastName}}"
Loops
Use range to iterate over arrays:
"items": [
{{range $index, $item := .items}}
{{if $index}},{{end}}
{
"id": {{$item.id}},
"name": "{{$item.name}}"
}
{{end}}
]
Conditionals
Use if statements for conditional logic:
{{if .isAdmin}}
"role": "administrator"
{{else}}
"role": "user"
{{end}}
Advanced Features
Function Composition
Use the pipe operator (|) to chain operations:
"name": "{{.name | uppercase}}"
"description": "{{.description | trim | lowercase}}"
Creating New Data Structures
Create and manipulate arrays and objects:
{{$users := createSlice}}
{{range .members}}
{{if eq .status "active"}}
{{$users = append $users .name}}
{{end}}
{{end}}
"activeUsers": [
{{range $i, $name := $users}}
{{if $i}},{{end}}
"{{$name}}"
{{end}}
]
Data Transformation
Group, filter, and transform data:
{{$categories := groupBy .products "category"}}
"categories": [
{{range $i, $category := keys $categories}}
{{if $i}},{{end}}
{
"name": "{{$category}}",
"count": {{count (index $categories $category)}},
"items": [
{{range $j, $product := index $categories $category}}
{{if $j}},{{end}}
"{{$product.name}}"
{{end}}
]
}
{{end}}
]
SGNL-to-PlainID Example
This transform converts SGNL authorization responses to PlainID format:
SGNL Auth Response Format
{
"decisions": [
{
"action": "PlainID_Dev",
"assetAttributes": {
"app_id": "256",
"approle_id": "1885",
"permission_id": "4798",
"permission_name": "Admin",
"permission_status": "Released"
},
"assetId": "Admin",
"decision": "Allow"
},
// More decisions...
],
"evaluationDuration": 83,
"issuedAt": "2025-04-18T05:26:29.412264083Z",
"principalId": "user123@example.com"
}
Transformation Template
The following example shows how to transform SGNL authorization data to PlainID format using advanced template features:
{
"tokenValidity": 0,
"response": [
{
"access": [
{{- /* Get unique asset IDs (paths) from decisions */ -}}
{{- $uniqueAssetIds := createSlice -}}
{{- range $i, $decision := .Decisions -}}
{{- if eq $decision.Decision "Allow" -}}
{{- $found := false -}}
{{- range $uniqueAssetIds -}}
{{- if eq . $decision.AssetID -}}
{{- $found = true -}}
{{- end -}}
{{- end -}}
{{- if not $found -}}
{{- $uniqueAssetIds = append $uniqueAssetIds $decision.AssetID -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- /* Loop through unique paths */ -}}
{{- range $pathIdx, $path := $uniqueAssetIds -}}
{{- if ne $pathIdx 0 }},{{ end }}
{
"path": "{{ $path }}",
"attributes": {
"RoleName": [
"{{ $path }}"
],
"IPControl_ID": [
0
],
"PermissionName": [
{{- /* Find all permissions related to this path */ -}}
{{- $permissionFound := false -}}
{{- range $i, $decision := $.Decisions -}}
{{- if and (eq $decision.Decision "Allow") (eq $decision.AssetID $path) -}}
{{- if $permissionFound -}},{{- end -}}
{{- $permissionFound = true -}}
"{{ $decision.AssetAttributes.permission_name }}"
{{- end -}}
{{- end -}}
{{- /* If no permissions found, use the path itself */ -}}
{{- if not $permissionFound -}}
"{{ $path }}"
{{- end -}}
],
"UserID": [
"{{ $.PrincipalID }}"
],
"EmployeeID": [
"{{ $.PrincipalID }}"
],
"AppName": [
{{- /* Find the action/AppName for this path */ -}}
{{- $appName := "" -}}
{{- range $i, $decision := $.Decisions -}}
{{- if and (eq $decision.Decision "Allow") (eq $decision.AssetID $path) -}}
{{- $appName = $decision.Action -}}
{{- break -}}
{{- end -}}
{{- end -}}
"{{ $appName }}"
]
}
}
{{- end }}
]
}
]
}
Explanation
This transformation demonstrates several advanced techniques:
- Creating arrays with
createSliceandappend - Checking for duplicates with nested loops
- Conditional output with
ifstatements - Accessing data across nested scopes with
$.prefix - Controlling whitespace with special syntax
- Using comment blocks in templates
Function Reference
String Functions
uppercase- Convert string to uppercaselowercase- Convert string to lowercasetrim- Remove whitespacesubstring "hello" 0 5- Extract part of a stringreplace "hello world" "world" "there"- Replace a substringsplit "a,b,c" ","- Split string into arrayjoin array "-"- Join array to stringcontains "hello world" "world"- Check if string contains pattern
Array Functions
createSlice- Create a new sliceappend slice elem- Append to a slicesort array- Sort an arrayreverse array- Reverse an arraydistinct array- Remove duplicatescount array- Count elementsfilter array predicate- Select matching elementsmap array function- Transform each elementflatten nested- Flatten nested arraysslice array 1 3- Extract subset of arraygroupBy items "property"- Group by propertyorderBy items "property"- Sort by properties
Object Functions
keys object- Get object keysvalues object- Get object valuesentries object- Convert to key-value pairsmerge obj1 obj2- Combine objectspick obj "key1" "key2"- Select propertiesomit obj "key"- Remove properties
Numeric Functions
add x y- Add numberssub x y- Subtract numbersmul x y- Multiply numbersdiv x y- Divide numbersabs -42- Absolute valuefloor 3.7- Round downceil 3.2- Round upround 3.14159 2- Round to precision
Conversion Functions
toJSON obj- Convert to JSON stringfromJSON str- Parse JSON string