This library provides a way to create JSON from templates that embed CEL expressions within them.
Templates are themselves valid JSON files and the input data is provided using a map[string]interface{}.
An example input of
{
"firstName": "Bob",
"donuts": 5
}
is processed by a template
{
"Name": "data.firstName",
"Rating": "data.donuts > 4 ? 'Donut fan' : 'Donut eater'"
}
to produce the output:
{"Name":"Bob","Rating":"Donut fan"}
Additional reference data can be provided when compiling the template, enabling lookups of additional information beyond that present in the input data.
An input of:
{
"firstName": "Bob",
"type": "u"
}
With a reference object of:
{
"categories": {
"u": "User",
"a": "Admin",
"s": "Superuser"
}
}
Can be used by a template of:
{
"Name": "data.firstName",
"Category": "ref.categories[data.type]"
}
To produce:
{"Name":"Bob","Category":"User"}
Template Fragments allow templates to reuse JSON objects, either once per list item or inline within the template.
An input of:
{
"name": "Bob",
"interests": [
"eating",
"sleeping"
]
}
A fragment called interestFragment with value:
{
"Activity": "'Hobby'",
"Kind": "args[0]"
}
A second fragment called summary with a value of:
{
"TotalActivities": "args[0]"
}
Combine with a template of:
{
"Person": "data.name",
"Interests": "data.interests.fragment ('interestFragment')",
"Other": "fragment ('summary', data.interests.size())"
}
To produce output of:
{
"Person": "Bob",
"Interests": [
{
"Activity": "Hobby",
"Kind": "eating"
},
{
"Activity": "Hobby",
"Kind": "sleeping"
}
],
"Other": {
"TotalActivities": 2
}
}
A basic way to start using the template library is:
package main
import (
"fmt"
celjsontemplates "github.com/cms103/cel-json-templates"
)
func main() {
t, _ := celjsontemplates.New(`{"Name": "data.firstName"}`)
res, _ := t.Expand(map[string]interface{}{"firstName": "Bob"})
fmt.Println(string(res))
}
Use this function to provide additional reference data under the "ref" top level name in the CEL expressions.
For example: celjsontemplates.New(templateData, celjsontemplate.WithRef((map[string]interface{}{"Name": "Value"})) would make ref.Name equal to Value.
Normally missing keys (e.g. data.doesNotExist) result in the JSON attribute being silently dropped. If you'd prefer to have an error instead pass celjsontemplate.WithMissingKeyErrors().
This function allows a map of fragment names to fragment template strings to be passed to the template: celjsontemplate.WithFragments(map[string]string{"FragmentName": "{}"})
The CEL execution environment can be modified using celjsontemplate.WithCelOptions to pass a list of cel.EnvOption values. For example to add additional string functions:
celjsontemplate.WithCelOptions (ext.Strings())
The CEL execution environment provides some additional functions for use with templates.
Calling remove_property() will remove a property from the Json output.
fragment ('name', ...) will expand the fragment called 'name', passing any further arguments in the args top level CEL name.
This function is also available on lists: [1,2].fragment ('name', ...) will expand the fragment 'name' twice, with args[0] containing the list element (1 then 2) and args[1] onwards containing any other arguments.
Some of the CEL macros don't play well with the additional data types and functions in CEL Json Templates. For example the expression [1,2].map (val, fragment ('name', val)) results in {"test":[{},{}]}. Use [1,2].fragment ('name') instead.