Skip to content

Expressions guide ​

The rules iPaaS uses to convert each field, with examples of source, expression and result.


Each mapping link is an expression: a short rule that defines how to get the value of a target field from the source. In most cases you do not need to write any expression. The AI generates all of them, and you can request adjustments in your own words in the Transformation panel or in the Assistant. This guide explains how iPaaS maps, so that you understand what was generated, know what to ask for and, if you want, edit the expression directly.

📘 Note

iPaaS expressions use the JSONata syntax. You do not need to learn JSONata to use iPaaS. Everything required for mapping is described here, and iPaaS accepts exactly the constructs in this guide.

How to read the examples ​

Each example shows three parts:

  • Source: the excerpt of the source JSON (the ERP sample in Inbound, the ME document in Outbound).
  • Expression: the rule that produces the value of the target field.
  • Result: the value that reaches the target.

Basic elements of an expression:

ElementHow to write itExample
Source fieldNames separated by a dotPedidoCompra.C7_NUM
Fixed textBetween single quotes'EMPRESA'
Fixed numberWithout quotes1
True, false, nullWithout quotestrue, false, null
FunctionStarts with $$uppercase(PedidoCompra.C7_NUM)

1. Referencing fields ​

Every path starts directly at the first level of the source and goes down through the objects with ..

Source

json
{ "PedidoCompra": { "C7_NUM": "000123", "C7_XNOME": "ACME", "C7_TIPO": "N" } }
TargetExpressionResult
Header.clientOrderIdPedidoCompra.C7_NUM"000123"
Header.vendorNamePedidoCompra.C7_XNOME"ACME"

❗️ Attention

Do not use prefixes before the first level, such as $.PedidoCompra, source.PedidoCompra or input.PedidoCompra. The path always starts at the name of the top-level field, and an expression with a prefix is rejected.

In Outbound, the ME document always has a single top-level field, named after the entity (for example order for orders and preOrder for pre-orders). All related information is inside it, so paths always start with that name: order.summary, order.items.quantity, order.items.taxInformation.calculationBasis. A path such as items.quantity, without order., finds nothing.

2. Direct copy ​

This is the most common case: the source value goes to the target unchanged. With the source from item 1:

TargetExpressionResult
Header.orderTypePedidoCompra.C7_TIPO"N"

The AI links fields by meaning, not only by name: C7_NUM → clientOrderId, CompanyCode → businessOrganizations.code. The confidence percentage indicates how sure it is. Identical names get high confidence, while synonyms or abbreviations get lower confidence and usually end up pending review.

3. Objects and nested fields ​

You do not need to worry about the target structure: iPaaS builds the intermediate objects on its own. Each expression handles a single final field, and iPaaS gathers all the fields that share the same object.

With the source from item 1:

TargetExpression
Header.clientOrderIdPedidoCompra.C7_NUM
Header.vendorNamePedidoCompra.C7_XNOME
Header.orderTypePedidoCompra.C7_TIPO

Result

json
{ "Header": { "clientOrderId": "000123", "vendorName": "ACME", "orderType": "N" } }

4. Fixed values ​

Use a fixed value when the target always requires the same value, with no match in the source.

TargetExpressionResult
businessOrganizations.virtualEntityField'EMPRESA'"EMPRESA"
A text field with the document type'PurchaseOrder'"PurchaseOrder"
A numeric field11

Do not confuse the text 'null' with the null value, which is null, without quotes.

📘 Note

The AI does not create fixed values on its own to complete the target. Fields without a source are left unlinked, and you decide what to do with them. The exception is when the sample itself makes it clear that the value is a constant, such as fixed parameters of a provider's request.


5. Lists ​

Lists (arrays) are the most important part of the mapping. iPaaS has two ways of filling a target list, and the choice depends on whether or not the source has a matching list.

5.1 List to list: one target item for each source item ​

When there is a list in the source, iPaaS iterates over that list and generates one item in the target for each source item. Inside the list, fields are referenced from the item, not from the beginning.

Source

json
{
  "PedidoCompra": {
    "C7_NUM": "000123",
    "C7_EMISSAO": "20250115",
    "Itens": [ { "C7_ITEM": "10", "C7_QTDE": "5", "C7_PRECO": "12.50" } ]
  }
}

Iterated list: PedidoCompra.Itens

TargetExpression (relative to the item)
Header.items.itemNumber$number(C7_ITEM)
Header.items.quantity$number(C7_QTDE)
Header.items.unitPrice$number(C7_PRECO)

Result

json
{ "Header": { "items": [ { "itemNumber": 10, "quantity": 5, "unitPrice": 12.5 } ] } }

With more items in the source, the target gets one item for each of them. In full notation, this rule looks like this:

text
[PedidoCompra.Itens.{ 'itemNumber': $number(C7_ITEM), 'quantity': $number(C7_QTDE), 'unitPrice': $number(C7_PRECO) }]

Rules for this form:

  • The target is always a list. Even if the ERP sends a single item as an object, and not as a list, the target gets a list with one item.
  • All fields of the same target list iterate over the same source list, written exactly the same way. If one field uses PedidoCompra.Itens and another uses Itens, iPaaS generates parallel lists instead of a single one. The board warns you when this happens.
  • Never build a list by joining loose fields from different lists. The values of a target item come from the same source item.

5.2 List built from single fields ​

When the target is a list but the source does not have a matching list, iPaaS builds a single item with values from anywhere in the source, including from different structures, and with fixed values. Here the paths are full paths, from the beginning of the source.

Source

json
{
  "PurchaseOrder": { "CompanyCode": "0001" },
  "CompanyCode": { "Description": "Matriz SP" }
}
TargetExpression
businessOrganizations.codePurchaseOrder.CompanyCode
businessOrganizations.descriptionCompanyCode.Description
businessOrganizations.virtualEntityField'EMPRESA'

Result

json
{
  "businessOrganizations": [
    { "code": "0001", "description": "Matriz SP", "virtualEntityField": "EMPRESA" }
  ]
}

❗️ Attention

In the same target list, use only one form: either all fields iterate over the same source list (5.1), or all of them come from single fields (5.2). Mixing the two forms in the same list causes a conflict when the document is assembled.

5.3 Using, inside the item, a value that is outside the list ​

Inside an iterated list, paths are relative to the item. To bring in a value that is outside the list, such as a header field, start the path with $$.. $$ represents the beginning of the source.

Source

json
{ "notaDe": "minha anotação", "itens": [ { "orderId": 1 }, { "orderId": 2 } ] }

Iterated list: itens

TargetExpression (relative to the item)
items.orderIdorderId
items.note$$.notaDe

Result

json
{
  "items": [
    { "orderId": 1, "note": "minha anotação" },
    { "orderId": 2, "note": "minha anotação" }
  ]
}

Without $$., iPaaS would look for notaDe inside each item, would find nothing, and the field would be left empty without any error.

In Outbound, the rule is the same: $$.order.summary brings the order summary into each item.

5.4 Information inside items ​

Information inside an item is accessed from the item, with the full path to it.

Source (Outbound)

json
{
  "order": {
    "id": "39581903",
    "summary": "Compra de material",
    "items": [
      { "id": "6", "code": "ITM-01", "quantity": 33.0, "taxInformation": { "calculationBasis": 100.0 } }
    ]
  }
}

Iterated list: order.items

TargetExpression (relative to the item)Result
PurchaseOrderItem.OrderQuantity$string(quantity)"33"
PurchaseOrderItem.TaxBasis$string(taxInformation.calculationBasis)"100"

If the nested information is itself a list, for example several taxes per item (order.items.taxInformation.taxes), it is iterated inside the item in the same way as in section 5.1. The target then gets a list of taxes in each item.

5.5 Fixed instances: businessOrganizations and attributes ​

In ME, the businessOrganizations lists (organizations: company, purchasing organization, plant, branch...) and attributes lists are usually filled from several single fields of the ERP, and each field represents a different item. For these cases, iPaaS builds one instance per entity, identified by the position [0], [1], [2]...

Source

json
{
  "CompanyCode": "M001",
  "CompanyName": "MD ENGENHARIA",
  "PurchasingOrganization": "01",
  "Attr2": "atributo"
}
TargetExpression
businessOrganizations[0].codeCompanyCode
businessOrganizations[0].descriptionCompanyName
businessOrganizations[0].virtualEntityField'EMPRESA'
businessOrganizations[1].codePurchasingOrganization
businessOrganizations[1].virtualEntityField'ORGANIZACAO_COMPRAS'
attributes[0].name'Atributo fixo'
attributes[1].nameAttr2

In the example, attributes[0] receives a fixed value ('Atributo fixo'), and attributes[1] comes from the source field Attr2.

Result

json
{
  "businessOrganizations": [
    { "code": "M001", "description": "MD ENGENHARIA", "virtualEntityField": "EMPRESA" },
    { "code": "01", "virtualEntityField": "ORGANIZACAO_COMPRAS" }
  ],
  "attributes": [ { "name": "Atributo fixo" }, { "name": "atributo" } ]
}

Rules for instances:

  • They apply to businessOrganizations and attributes at the first level of the document and also to the nested lists items.attributes, items.businessOrganizations, locations.businessOrganizations, requestItems.attributes and requestItems.businessOrganizations. They do not apply to other lists, such as items.
  • In a nested list, the same instances repeat in every item of the parent list, each one with that item's values. See the example below.
  • With a single entity in the source, there are no instances: form 5.2 applies.
  • All fields of the same entity use the same position: CompanyCode and CompanyName describe the same company, so both go to [0].
  • Positions are sequential starting at [0], in the order in which the fields appear in the source.
  • When a list uses instances, all of its fields use a position. Do not mix businessOrganizations.code with businessOrganizations[1].code.
  • Classification fields, such as virtualEntityField and entityType, are codes configured for your organization in ME. The AI only fills them in when the name of the source field makes the entity unambiguous. When in doubt, the field is left for you to complete. Suggestions with instances have limited confidence and appear as pending review.

On the mapping board, use Add instance to create a new position and Remove instance to delete it. The following positions are renumbered.

Example with a nested list (items.attributes)

Source:

json
{
  "itens": [
    { "codigo": "A1", "cor": "azul", "material": "aco" },
    { "codigo": "B2", "cor": "verde", "material": "plastico" }
  ]
}

Iterated list: itens

TargetExpression (relative to the item)
items.codecodigo
items.attributes[0].name'Cor'
items.attributes[0].valuecor
items.attributes[1].name'Material'
items.attributes[1].valuematerial

Result: both instances appear in every item, with that item's values.

json
{
  "items": [
    { "code": "A1", "attributes": [ { "name": "Cor", "value": "azul" }, { "name": "Material", "value": "aco" } ] },
    { "code": "B2", "attributes": [ { "name": "Cor", "value": "verde" }, { "name": "Material", "value": "plastico" } ] }
  ]
}

5.6 Choosing one item from a list for a single field ​

Sometimes the source is a list and the target accepts only one value. For example, in Outbound, the ERP wants a single CompanyCode field, but the ME document has a businessOrganizations list with the company, the plant and other organizations. In these cases iPaaS needs to know which item to use.

The recommended way is to choose the item by a field that identifies it.

Source (Outbound, pre-order)

json
{
  "preOrder": {
    "businessOrganizations": [
      { "code": "111111", "description": "MATRIZ", "virtualEntityField": "EMPRESA" },
      { "code": "131313", "description": "Demonstração 2", "virtualEntityField": "CENTRO" }
    ]
  }
}
TargetExpressionResult
CompanyCodepreOrder.businessOrganizations[virtualEntityField = 'EMPRESA'].code"111111"
PlantpreOrder.businessOrganizations[virtualEntityField = 'CENTRO'].code"131313"

Figure 1. List to single field link with the item already chosen by the virtualEntityField field

Figure 2. Expression generated for the CompanyCode field: the item of the businessOrganizations list is chosen by the value of virtualEntityField

In the demo flow shown in the figure, the ME order has the organization with virtualEntityField = MATRIZ, and the AI generated order.businessOrganizations[virtualEntityField = 'MATRIZ'].code for the SAP CompanyCode. The board shows the applied choice on the link line itself (virtualEntityField = MATRIZ); click it to review or change the field and the value.

On the board, these links appear with the Choose item warning. Click the warning and enter the Field and the Value that identify the item (in the example, virtualEntityField = EMPRESA).

Choosing by position ([0], [1]) should only be used when no field identifies the items:

TargetExpressionResult with the source above
PurchasingOrganizationpreOrder.businessOrganizations[1].code"131313"

❗️ Attention

The order of the items in a list is not guaranteed. If the list comes in a different order in another document, position [1] starts returning another item, and the wrong value goes to the ERP without any error. For this reason, the AI only suggests choosing by position when there is no alternative, and always with low confidence, so that you review it.


6. Type conversion ​

When the source type is different from the type required by the target, the value must be converted. The board flags these links as Incompatible types, and the AI applies the conversion automatically whenever it identifies the difference.

ConversionSourceExpressionResult
Text → number{ "C7_ITEM": "10" }$number(C7_ITEM)10
Number → text{ "quantity": 33.0 }$string(quantity)"33"
Text 'true'/'false' → true/false{ "active": "false" }$lowercase(active) = "true"false
Remove leading zeros (number){ "C7_NUM": "000123" }$number(C7_NUM)123
Remove leading zeros (text){ "C7_NUM": "000123" }$string($number(C7_NUM))"123"

If the source already has the required type, no conversion is applied.

❗️ Attention

Do not use $boolean() to convert the texts "true"/"false": it returns true for any non-empty text, including "false". Compare the text instead, as in $lowercase(field) = "true".

7. Text ​

What to doSourceExpressionResult
Concatenate with a separator{ "C7_XNOME": "MARCIA", "C7_XSOBRENOME": "SOUZA" }C7_XNOME & '-' & C7_XSOBRENOME"MARCIA-SOUZA"
Concatenate with a space(the same)C7_XNOME & ' ' & C7_XSOBRENOME"MARCIA SOUZA"
Lowercase{ "C7_XNOME": "MARCIA" }$lowercase(C7_XNOME)"marcia"
Uppercase{ "C7_XNOME": "marcia" }$uppercase(C7_XNOME)"MARCIA"
Part of the text{ "C7_EMISSAO": "20250115" }$substring(C7_EMISSAO, 0, 4)"2025"
Replace parts{ "data": "2025-01-15" }$replace(data, '-', '')"20250115"

$substring(text, start, length) counts from 0. In the Transformation panel, just describe what you want, for example "concatenate the two fields with a hyphen and make everything uppercase".

8. Dates ​

YYYYMMDD → ISO 8601 date

SourceExpressionResult
{ "C7_EMISSAO": "20250115" }( $d := C7_EMISSAO; $substring($d,0,4) & '-' & $substring($d,4,2) & '-' & $substring($d,6,2) & 'T00:00:00Z' )"2025-01-15T00:00:00Z"

The expression stores the value in $d and then builds the date in parts. Blocks between parentheses, with ; separating the steps, are used to give a name to an intermediate value and make the rule easier to read.

ISO 8601 date → YYYYMMDD

text
C7_DATPRF ? $replace($substring(C7_DATPRF, 0, 10), '-', '') : null

It takes the first 10 characters (YYYY-MM-DD), removes the hyphens and only applies the rule if the field has a value. See Protection against empty fields.

9. Numbers and calculations ​

Available operators: +, -, *, /. Use parentheses to set the order of operations.

What to doExpression
Divide and round to 2 decimal places$round(PedidoCompra.VALOR / 10, 2)
Multiply quantity by price, converting the texts into numbers$number(C7_QTDE) * $number(C7_PRECO)

With the source from section 5.1 ("C7_QTDE": "5" and "C7_PRECO": "12.50"), the multiplication results in 62.5.

10. Conditionals ​

Use condition ? value-if-true : value-if-false.

ExpressionSourceResult
PedidoCompra.TIPO = 'NB' ? 'STANDARD' : 'OUTROS'TIPO = "NB""STANDARD"
(the same)TIPO with any other value"OUTROS"

For more than two options, chain conditionals or, even better, use a lookup table.

11. Default value and empty fields ​

Default value ​

When the field may come empty or missing and the target needs a value, use the field itself as the condition:

ExpressionSourceResult
PedidoCompra.C7_XNOME ? PedidoCompra.C7_XNOME : 'SEM_NOME'{ "PedidoCompra": { "C7_XNOME": "ACME" } }"ACME"
(the same){ "PedidoCompra": { } }"SEM_NOME"

Protection against empty fields ​

The sample used in the mapping is a single record, and the fact that a field is filled in it does not guarantee that it will always come filled in. When a field arrives with a null value in a text function ($substring, $replace, $uppercase, $lowercase...), the conversion of the entire document fails, not only that field's conversion.

For this reason, iPaaS protects by default every field that goes through one of these functions, checking whether it has a value before applying the function:

text
PedidoCompra.Itens.C7_DATPRF ? $replace($substring(PedidoCompra.Itens.C7_DATPRF, 0, 10), '-', '') : null

instead of:

text
$replace($substring(PedidoCompra.Itens.C7_DATPRF, 0, 10), '-', '')

With the protection, a C7_DATPRF with null results in null and the rest of the document is converted normally. Without it, the entire conversion fails.

If you edit an expression manually, keep this protection. A missing field (one that does not even appear in the JSON) does not cause an error; it is simply not filled in. The risk is in a field that is present with null.

12. Lookup tables ​

To convert codes from one system to another, declare a table and query it with $lookup:

text
( $moeda := { 'USD': 'DOLAR', 'BRL': 'REAL' }; $lookup($moeda, PedidoCompra.MOEDA) )
PedidoCompra.MOEDAResult
"USD""DOLAR"
"BRL""REAL"

If the code does not exist in the table, the field is left empty. To have a default value, combine it with the default value rule.

13. Totals and counts ​

What to doExpression
Sum a field across all items of a list$sum(PedidoCompra.Itens.C7_VALOR)
Count the items of a list$count(PedidoCompra.Itens)

With the source from section 5.1, which has a single item, $count(PedidoCompra.Itens) results in 1.


14. Connector request mapping ​

In a connector's request mapping, the source is always a simple object with the ME search parameters, without lists:

OperationSource
getAll{ "searchTerm": "...", "pageNumber": 1, "pageSize": 20 }
getById and getOffers{ "productId": "..." }

Therefore:

  • expressions are always direct or use the conversion and text functions above;
  • if the provider requires a list with a single code, just link productId. iPaaS places the value inside the list automatically;
  • when the sample is a query string, each parameter becomes a first-level field;
  • fixed provider parameters, such as region and language, are entered as a fixed value when they appear in the pasted sample.

Example with a JSON body (POST resource). Pasted sample:

json
{ "clientDetails": { "clientId": "192533129MEP", "accountNumber": "800014904" }, "searchQuery": "drill" }
Target (provider)Expression
searchQuerysearchTerm

Example with a query string (GET resource). Pasted sample: ?productRegion=US&locale=en_US&keyword=drill&pageNumber=1

Target (provider)Expression
keywordsearchTerm
pageNumberpageNumber
productRegion'US'
locale'en_US'

Example with a single-code list (getById). Pasted sample: { "productCodes": ["3EB46"], "clientDetails": { ... } }

Target (provider)ExpressionSent to the provider
productCodesproductId["<productId>"]

15. What is not supported ​

To ensure that the mapping works the same way in testing and in production, iPaaS only accepts the constructs described in this guide. The following are not accepted:

ConstructAlternative in iPaaS
Filtering the items of a list by a condition, such as Itens[C7_QTDE > 0]Not available. All items of the source list are carried over to the target. The only selection by condition accepted is choosing one item for a single field, in Outbound.
Wildcards * and **Use the full path of the field.
Chaining with ~>Nest the functions: $uppercase($substring(C7_EMISSAO, 0, 4)).
Higher-order functions ($map, $filter, $reduce...)Use list to list.
Functions not in the quick referenceCombine the available functions or use a lookup table.
Prefixes $., source. and input. in the pathStart the path at the top-level field.

Function quick reference ​

FunctionWhat it doesExample
$number(x)Converts text into a number$number('000123') → 123
$string(x)Converts into text$string(33) → "33"
$boolean(x)Converts into true/false. Attention: any non-empty text becomes true, including 'false'; only empty text becomes false$boolean('false') → true
$uppercase(x)Uppercase letters$uppercase('marcia') → "MARCIA"
$lowercase(x)Lowercase letters$lowercase('MARCIA') → "marcia"
$substring(x, start, length)Part of a text$substring('20250115', 0, 4) → "2025"
$replace(x, from, to)Replaces parts$replace('2025-01-15', '-', '') → "20250115"
$round(x, places)Rounds$round(62.456, 2) → 62.46
$sum(list)Sums the values$sum([5, 12.5]) → 17.5
$count(list)Counts the items$count([1, 2]) → 2
$lookup(table, key)Queries a lookup table$lookup({'USD': 'DOLAR'}, 'USD') → "DOLAR"
&Concatenates texts'MARCIA' & '-' & 'SOUZA' → "MARCIA-SOUZA"
? :ConditionalTIPO = 'NB' ? 'STANDARD' : 'OUTROS'
$$Beginning of the source, used inside lists$$.notaDe