celjsontemplates

package module
v0.0.0-...-dfdd542 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 9, 2023 License: MIT Imports: 11 Imported by: 0

README

CEL Json Templates

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{}.

Basic Example

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

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

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
    }
}

Getting Started

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))
}

API Options

WithRef

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.

WithMissingKeyErrors

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().

WithFragments

This function allows a map of fragment names to fragment template strings to be passed to the template: celjsontemplate.WithFragments(map[string]string{"FragmentName": "{}"})

WithCelOptions

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())

CEL Json Template - additional Functions

The CEL execution environment provides some additional functions for use with templates.

remove_property

Calling remove_property() will remove a property from the Json output.

fragment

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.

Limitations / known issues

Built-in CEL macros.

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.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func UnmarshallJson

func UnmarshallJson(jsonData []byte) (*orderedmap.OrderedMap[string, any], error)

Types

type Template

type Template interface {
	// Expand runs the CEL expressions in the template against the provided data and returns the result
	Expand(data map[string]interface{}) ([]byte, error)
}

Template represents a CEL JSON Template

func New

func New(template string, config ...TemplateConfigFunc) (Template, error)

Creates a new Template using the provided input and options

type TemplateConfigFunc

type TemplateConfigFunc func(t *celTemplate)

WithXXX functions provide configuration options by returning TemplateConfigFunc

func WithCelOptions

func WithCelOptions(moreOptions []cel.EnvOption) TemplateConfigFunc

WithCelOptions allows additional CEL EnvOptions to be used in the template. This can be used to add custom functions and other CEL behaviour modifications

func WithFragments

func WithFragments(templates map[string]string) TemplateConfigFunc

WithFragments registers a map of templates that can be used within this template.

func WithMissingKeyErrors

func WithMissingKeyErrors() TemplateConfigFunc

WithMissingKeyErrors will trigger errors when a template CEL expression refers to a missing key. By default such errors are suppressed

func WithRef

func WithRef(ref map[string]interface{}) TemplateConfigFunc

WithRef provides a "ref" object in the CEL environment This can be used to pass reference data used in the template For example to map values across data models

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL