A mapping in Flogo can be used to assign the value of a parameter (flow input, for example) to that of an input parameters of an activity or to the value of another flow scoped variable.
Flogo infers the mapping type based on the structure of the mapping itself. The following list details the specifics around each mapping type.
Type | Description | Format |
---|---|---|
literal | A literal mapping. For example, mapping the string “hello” to a string typed input. | Simply enclose your string literal in double quotes: " " |
expression | Expression mapping. This enable using functions and expression condition in mamping | The mapping string should begin with an equals character = |
object | Complex object. Used when a JSON-based object must be built and values assigned from other scoped properties/activity outputs. | See details below. |
array | Array mapping. Mapping an Array of Objects. | See details below |
Mappings are quite straightforward, for example:
{
"isbn": "=$.event.isbn"
}
The above mapping indicates that the value of event.isbn
from a trigger input should be mapped to the action input named isbn
. Consider two additional samples, below you will find a mapping to an activity from a $flow
scoped property, a literal mapping, as well as an object type object mapping.
Type expression from a flow-scoped property
{
"isbn": "=$flow.isbn"
}
Type literal:
{
"isbn": "12937"
}
Type object:
{
"bookDetails": {
"mapping": {
"Author": "=$flow.author",
"ISBN": "=$flow.name",
"Price": "$20"
}
}
}
The literal mappings are pretty simple to understand, as are the flow scoped expression mappings. However type object does require a bit of an explanation. The mapping
object is used to define how the object should be constructed and the various fields within the object mapped. This is done for performance reasons to avoid any unnecessary parsing of property values.
If you assign the value of an array then that param will be treated as an array, likewise for a string, int, etc. For example, let us pretend $flow.Author
is an array, then the Author object would also be an array. In otherwords, direct assignment is occurring.
The WebUI insulates you frome much of this understanding and will infer the correct mapping type.
Additional type expression:
{
"data.description": "=string.concat(\"The pet category name is: \", $activity[rest_3].result.category.name)",
}
The above sample leverages the output of a REST Invoke activity to get a pet from the public petstore service.
The mapper uses a string concat function string.concat(str1, str2, str3)
and assigns the function return to the description
field.
Type array:
Example 1: iterator array $fow.store.books
and assign value to books
{
"books": {
"mapping": {
"@foreach($flow.store.books)": {
"author": "=$loop.author",
"title": "=$loop.title",
"price": "=$loop.price"
}
}
}
}
The above example showing how array mapping works. the mapping
node same with object mapper
which is used to identity an object mapping.
The example: Iterate $flow.store.books
source array’s author, title and price to target array books
, The final target books:
{
"books": [
{
"author":"xxxx",
"titile":"xxxx",
"price": 33.33
}
]
}
Description of the mapping.
Flogo will resolve mappings with the following reference. Note the scopes table below, which indicates what objects are accessible within what scope.
Scope | Description |
---|---|
$env | Used to resolve an environment variable |
$property | Used to resolve properties from the global application property bag |
$flow | Used to resolve params from within the current flow. If a flow has a single trigger and no input params defined, then the output of the trigger is made available via $flow |
$activity | Used to resolve activity params. Activities are referenced by id, for example, $activity[acivity_id].activity_property. |
$iteration[key] && $iteration[value] | Used to resolve data scoped to a current iterator |
Flogo has the concept of mapping resolvers and resolvers are contained within a specific scope, hence not all objects can be accessed from anywhere within the scope.
Mapper | Scope |
---|---|
Trigger->Settings | env and property resolvers |
Trigger->Handler->Settings | env and property resolvers |
Trigger->Handler->actionMapper/input | Trigger ouput <– “value” field - only property and env resolver can be used. That is, only the output of the trigger or an environment variable can be used here. |
Trigger->Handler->actionMapper/output | action scope. Properties defined as ahe output of the flow can be used. |
Action->Flow->Activity->inputMapper/input | flow <– “value” field - all resolvers can be used |
Action->Flow->Activity->inputMapper/output | activity input |
Action->Flow->Activity->outputMapper/input | activity output |
Action->Flow->Activity->outputMapper/output | flow |
Link Expression | all resolvers can be used for link expressions. |
Flogo leverages a few simple syntax paradigms when mapping. The first being, the $
character which is used when accessing/reading a property and the pre-fixed .
indicates that the value is available within the current scope. For example, consider the following mapping:
{
"isbn": "=$.event.isbn"
}
The above mapping is from the Trigger/Handler, which we know, based on the indication of the .
, we can only access trigger scoped (output) variables, thus event.isbn
is within the trigger scope, as indicated by the preceding .
.
What if you’re accessing a property out of the immediate scope? The mapping should be prefixed with the $
special character, indicating to the resolver that we’re accessing a property out of the immediate scope. For example, consider the following.
"input": {
"message": "=string.concat(\"Hello \", $flow.name)"
}
This mapping is associated with Action->Flow->Activity->inputMapper. We know that all resolvers can be used within the context, however none of the variables would be within the immediate scope, hence the $
should be used. For example, in the above snippet, we’re grabbing the value of the flow variable named name
, hence $flow.name
is used. If we wanted to grab the value of an environment variable we could use $env.VarName
.
Most of the time you wont want to perform a direct assigning from one complex object to another, rather you’ll want to grab a simple type property from one complex object and perform a direct assigning to another property. This can be done accessing children using a simple dot notation. For example, consider the following mapping.
{
"someObject": {
"mapping": {
"Title": "=$activity[rest_3].result.items[0].volumeInfo.title",
"PublishedDate": "=$activity[rest_3].result.items[0].volumeInfo.publishedDate",
"Description": "=$activity[rest_3].result.items[0].volumeInfo.description"
}
}
}
someObject is a type object
and has the properties Titie
, PublishedDate
, Description
which are being mapped from the response of an activity, this is fetched using the $activity
scope. Consider one of the examples:
$activity[rest_3].result.items[0].volumeInfo.title
We’re referencing the result property from the activity named rest_3. We’re then accessing an items array (the first entry of the array) to another complex object, where finally we’re at a simple string property named title.
Most of time you want to add some custome logic to the mapping, such as concat/substring/length of a string or generate a random number base on a range and so on. any logic you want to add you can come up with an function. Refer to the functions repository for all available functions. Also note, you can install custom functions using the CLI’s flogo install
command.
{
"description": "=string.concat(\"The pet category name is: \", $activity[rest_3].result.category.name)"
}
The function or expression condition can also use to link expreesion in branch, any functions that return a boolean can use in link expression.
{
"from": "log_2",
"to": "log_4",
"type": "expression",
"value": "$activity[rest_3].result.category.name == \"BOOK\""
}
or
{
"from": "log_2",
"to": "log_4",
"type": "expression",
"value": "string.len($flow.name) > 0"
}
There are lots of use cases for array mapping, map entire array to another or iterator partial array to another with functions The array mapping value comes from a JSON format
Case 1: iterator array $fow.store.books
and assign value to books
{
"books": {
"mapping": {
"@foreach($flow.store.books)": {
"author": "=$loop.author",
"title": "=$loop.title",
"price": "=$loop.price"
}
}
}
}
Case 2: Copy original array $fow.store.books
to target array books
{
"books": {
"mapping": {
"@foreach($flow.store.books)": {
"=": "$loop"
}
}
}
}
Case 3: Iterator array $fow.store.books
and assign to primitive array titles
{
"titles": {
"mapping": {
"@foreach($flow.store.books)": {
"=": "$loop.title"
}
}
}
}
Case 4: Accessing parent loop data.
{
"books": {
"mapping": {
"@foreach($flow.store.books, bookLoop)": {
"title": "=$loop.title",
"price": "=$loop.price",
"author": {
"@foreach($loop.author, authorLoop)": {
"firstName": "=$loop.firstName",
"lastName": "=$loop[authorLoop].lastName",
"bookTitle": "=$loop[bookLoop].title"
}
}
}
}
}
}
Case 5: Using fixed array, same as object mapper
{
"store": {
"mapping": {
"store": {
"books": [
{
"author": "=string.concat($activity[rest].result.firstName, $activity[rest].result.lastName)",
"title": "Five little ducks",
"price": 19.99
},
{
"author": "=string.concat($activity[rest2].result.firstName, $activity[rest2].result.lastName)",
"title": "I love trucks",
"price": 11.99
}
]
}
}
}
}
@foreach(source, loopName<optional>)
to indicate doing array mapping on source data$loop.xxx
to access the current loop data xxx
is the object field name$loop[loopName].xxx
to access specific loop dataNote You can use any literal, functions, expression in array mapping.
{
"books": {
"mapping": {
"@foreach($flow.store.books)": {
"author": "=string.concat($activity[rest].result.firstName, $activity[rest].result.lastName)",
"title": "Five little ducks",
"price": 19.99
}
}
}
}