Skip to content

Data Processing

APICHAP configuration comes with a data processing syntax:

  1. Schema Generation
  2. Conditions
  3. Placeholders
  4. Converting Types
  5. Concatenation and Arithmetic Operations

Schema Generation

When you are in need of data in a specific dataformat you should use schema. With a schema you are able to build an entity unindependenly of the dataformat behind it. For more details on special rules regarding specific data formats used in combination with schema, refer to the Schema Guidelines section.

Schemas can be used to build:

  • The response of your API
  • A requestbody to send to 3rd party API requests
  • A file you are writing on any datasource such as an FTP-Server

In all of those occasions the configuration structure to build them is exactly the same.

How to create a schema

The structure can be build using those types:

Simple Value

Specify a primitive attribute by setting key: value to your yaml configuration.

It´s possible to concat values with '.', '+', '-', ... Find details on value concatenation here.

Configuration Result
schema:
  firstname: VALUE(contact, $.results[0].properties.firstname)
{
    "firstname": "Maria"
}
schema:
  animals: TEXT(List of Animals ) . LIST_TO_STRING(ff1, $.animals, "* %s", "|")
{
    "animals": "List of Animals * Dog | * Cat | * Bird"
}

List (Array)

Specify an array with the following attributes:

Field Description
list Specify the an array, used to loop through and build the JSON objects below.
item Either a new object or direct value (primitive, like a string array).
Configuration Result
> Use @ the current iteration of the list.
schema:
  # Value needs to be an array
  list: VALUE(fulfillment_contacts, $.persons) 
  item:
    firstname: VALUE(@, $.firstname) # Specify a @ value
    ...
[
  {
    "firstname": "Maria"
  }, {
    "firstname": "Alex"
  }
]
schema:
  # Value needs to be an array
  list: VALUE(fulfillment_contacts, $.persons) 
  item: VALUE(@, $.firstname) # Specify a primitive value directly.
[
  "Maria", 
  "Alex"
]
> You are able to use @@ to get the iteration from before and so on.
schema:
  # Value needs to be an array
  list: VALUE(fulfillment_contacts, $.groups) 
  item: 
    list: VALUE(@, $.persons)
    item:
      firstname: VALUE(@, $.firstname) # Specify a primitive value directly.
      groupName: VALUE(@@, $.group_name) # Specify a group name.
[
  "Maria", 
  "Alex"
]

Object

Specify an object with the following attributes:

Field Description
object OPTIONAL; Specify data to be used with @ in your object
item Your Object
Configuration Result
schema:
  person:
    # Specify an object without using the object attribute
    item:
      firstname: VALUE(person_ff, $.person.firstname) 
      lastname:  VALUE(person_ff, $.person.lastname) 
{
  "person": {
    "firstname": "Maria",
    "lastname": "Volovik"
  }
}
schema:
  person:
    # Specify with an object to use the @ syntax below.
    object: VALUE(person_ff, $.person) 
    item: 
      firstname: VALUE(@, $.firstname) 
      lastname:  VALUE(@, $.lastname)
{
  "person": {
    "firstname": "Maria",
    "lastname": "Volovik"
  }
}

Map (Dictionary)

Specify a JSON map (dictionary) with the following attributes

Field Description
map Specify the map or dictionary.
item Your Map Object or direct mapping.
Configuration Result
schema:
  person:
    # Set the whole dictionary person into our person field. 
    # The input VALUE must be a dictionary.
    map: VALUE(person_ff, $.person)
{
  "person": {
    "firstname": "Maria",
    "lastname": "Volovik",
    "age": 32
  }
}

Full Example

A full response builder could look like that:

schema:
  list: VALUE(get_news, $) # Needs to be an array
  items:
    id: VALUE(@, $.id) # Needs to be an array
    title: VALUE(@, $.name) # Needs to be an array
    authors:
      list: VALUE(authors, $)
      items:
        firstname: VALUE(@, $.firstname)
        lastname: VALUE(@, $.firstname)
    news_time: VALUE(@, $.newstime)

Building the following JSON result:

[
  {
    "id": 1, 
    "title": "APICHAP v1 is out now!",
    "authors": [
      {
        "firstname": "Alex",
        "lastname": "Lee"
      },{
        "firstname": "Maria",
        "lastname": "Mustermann"
      },
    ],
    "news_time": "2024-04-25T13:01:40+00:00"
  }, 
  {
    "id": 2,
    "title": "Amazing Devtool Released",
    "authors": [
      {
        "firstname": "Alex",
        "lastname": "Lee"
      }
    ],
    "news_time": "2024-04-25T15:01:40+00:00"
  }
]

Condition

In multiple occasions you are able to specify a condition. This can happen in the following fields: - Every if in your configuration - A condition when to leave a loop before finished loopbreak

Operator Description
== Two values are equal.
!= Two values are not equal.
< Value 1 is smaller then value 2
<= Value 1 is smaller or equal to value 2
> Value 1 is bigger then value 2
>= Value 1 is bigger or equal to value 2
^= The text in value 1 starts with the text value 2
=^ The text in value 1 ends with the text value 2
# Check if input parameter is english
PARAM(Content-Language) == TEXT(en)
# Check if input parameter id is not equal to the result of ff1.id
PARAM(Content-Language) != VALUE(ff1, $.id)
# Check if the field age from result of fulfillment called ff1 is bigger then 30
VALUE(ff1, $.age) > INTEGER(30)
if: TEXT(1234) ^= TEXT(12000)  // Leads to true
if: TEXT(hello world) =^ TEXT(world)  // Leads to True
if: TEXT(hello world) =^ TEXT(hello)  // Leads to False

Placeholder

Whenever you are in need of using dynamic values in another string, use a method within a placeholder. A placeholder is necessary in every field that does not expect a method to begin with.

Such as:

  • query
  • a request url´s url: https://${ENV(URL)}/path
  • Use another method in a JSONPath VALUE(test, $.Content[?(@.Id == ${VALUE(@, $.id)})].ProductNo)
  • Secrets in fields such as a datasource´s user or passwords

${PLACEHOLDER VALUE}

# Placeholder for the Header Parameter Content-Language
SELECT * FROM news WHERE lang == ${PARAM(Content-Language)}
# Placeholder for a Path Parameter called id
SELECT * FROM news WHERE id == ${PARAM(id)}
# Placeholder for a field userid retrieved from the requestbody json: { "userid":"1", "username":"Maria" }
SELECT * FROM user WHERE id == ${BODY($.userid)}
# Placeholder to use a value called id from a fulfillments (fulfillment name: ff1) result. 
SELECT * FROM notes_changelog WHERE notes_id == ${VALUE(ff1, $.id)}

Converting Types

Sometimes the data retrieved from a data source may not be in the expected format, and type conversion is necessary. You can combine existing methods to perform type conversion.

Assuming a PARAM(id) is a string you could:

  • Convert to Integer: You can convert a string or text value to an integer by combining the INTEGER and TEXT methods. INTEGER(PARAM(id))
  • Convert to Double: Similarly, you can convert a string or text value to a double. DOUBLE(PARAM(id))
  • Convert to Long: Similarly, you can convert a string or text value to a double. DOUBLE(PARAM(id))
  • Convert to Boolean: Similarly, you can convert a string or text value to a double. DOUBLE(PARAM(exists)) (Converts from true / false).

Concatenation and Arithmetic Operations

In this section, we'll cover how to concatenate strings and perform basic arithmetic operations like addition, subtraction, multiplication, division, and modulo on values.

Concatenation:

To concatenate two strings, use the . operator. This combines two or more text values into a single string.

TEXT(This is) . TEXT( the text)
This will result in: This is the text.

Arithmetic Operations:

You can perform arithmetic operations on values using standard operators. These operations can be combined for more complex calculations.

Addition:

Use the + operator to add values.

INTEGER(1) + INTEGER(2)  // Results in: 3

Subtraction:

Use the - operator to subtract values.

INTEGER(1) + INTEGER(2) - INTEGER(1)  // Results in: 2

Multiplication:

Use the * operator to multiply values.

INTEGER(1) * INTEGER(2)  // Results in: 2

Division:

Use the / operator to divide values.

INTEGER(4) / INTEGER(2)  // Results in: 2

Modulo:

Use the % operator to get the remainder after division.

INTEGER(2) % INTEGER(1)  // Results in: 0