Write a custom transformation

Developer reference for HighCohesion transformation files: field types, lists, pre-formatting and post-formatting functions.

This page is the developer reference for HighCohesion transformation files. A transformation is a JSON document that maps the payload in received from a source system to the payload out sent to a destination. It runs in four stages: pre-formatting reshapes the incoming payload; field types and lists build the output structure; post formatting functions change individual values; and list post formatting functions reshape finished lists.

Every function below follows the same layout: what it does, the options it takes, and a worked example showing the payload in, the transformation, and the resulting payload out. All examples were generated by running the transformation engine.

Field types

A transformation file is a JSON document that describes the payload out (the data sent to the destination) in terms of the payload in (the data received from the source). Every key in the file becomes a key in the output; the value of each key is a small object whose field type tells the transformer where the value comes from.

Field types are JSON keys that start and end with a * character, for example "*static_value*" or "*ppk*". Most field types accept an optional *post_format* list that is applied to the value after it has been resolved (see Post formatting).

Paths are written with dots. customer.first_name reads the first_name key inside customer; numeric parts index into lists, so line_items.0.sku is the SKU of the first line. Inside a *list* the path is relative to the current list item; prefix the path with a dot (.order.name) to read from the root of the payload instead.

*static_value*

Writes a fixed value into the output. The value can be any JSON type: string, number, boolean, null, object or list.

Options

  • *static_value* — The literal value to output.

  • *post_format* — Optional list of post formatting functions to apply to the value.

Example

Payload in

{
  "order": {"name": "#1001"}
}

Transformation

{
  "status": {"*static_value*": "Released"},
  "location_id": {"*static_value*": 1432526},
  "active": {"*static_value*": true}
}

Payload out

{"status": "Released", "location_id": 1432526, "active": true}

*ppk*

Producer Payload Key. Reads a value from the payload in at the given path. If the path does not exist the field is output as an empty string.

When *ppk* is given a list of paths, the values found are joined together with a single space. Use *ppk_join* if you need a different separator.

Options

  • *ppk* — Path to the value, or a list of paths to join with a space. Prefix with . to read from the root of the payload while inside a list.

  • *post_format* — Optional list of post formatting functions.

Top-level, nested and joined paths

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "order_number": {"*ppk*": "order.name"},
  "email": {"*ppk*": "order.email"},
  "full_name": {
    "*ppk*": ["order.customer.first_name", "order.customer.last_name"]
  }
}

Payload out

{
  "order_number": "#1001",
  "email": "joe.bloggs@example.com",
  "full_name": "Joe Bloggs"
}

Reading from the root while inside a list

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "lines": {
    "*list*": "order.line_items",
    "*list_fields*": {
      "sku": {"*ppk*": "sku"},
      "order_number": {"*ppk*": ".order.name"}
    }
  }
}

Payload out

{
  "lines": [
    {"sku": "TSHIRT-M", "order_number": "#1001"},
    {"sku": "CAP-01", "order_number": "#1001"}
  ]
}

*ppk_join*

Joins several values from the payload in with a separator of your choice. Values that resolve to None are skipped.

Options

  • *joins* — List of *ppk* blocks to read, for example {"*ppk*": "address.city"}. Each block may carry its own *post_format*.

  • *join_with* — Separator placed between the values. Defaults to a single space.

  • *post_format* — Optional list of post formatting functions.

Example

Payload in

{
  "address": {
    "line1": "12 High Street",
    "line2": "Flat 3",
    "city": "Bristol",
    "postcode": "BS1 4DJ"
  }
}

Transformation

{
  "address": {
    "*ppk_join*": {
      "*joins*": [
        {"*ppk*": "address.line1"},
        {"*ppk*": "address.line2"},
        {"*ppk*": "address.city"},
        {"*ppk*": "address.postcode"}
      ],
      "*join_with*": ", "
    }
  }
}

Payload out

{"address": "12 High Street, Flat 3, Bristol, BS1 4DJ"}

*ppk_math*

Performs a single arithmetic operation between two values read from the payload in. Both values are cast to floats. If either value is missing or not numeric the field is output as null (after any *post_format* is applied).

Options

  • *ppk_math* — A three-element list: [path_a, operator, path_b]. Supported operators are +, -, * and /. Any other operator is treated as +.

  • *post_format* — Optional list of post formatting functions, for example math_round.

Example

Payload in

{
  "tax_lines": [
    {"price": "7.80"}
  ],
  "quantity": 3
}

Transformation

{
  "unit_tax": {
    "*ppk_math*": ["tax_lines.0.price", "/", "quantity"],
    "*post_format*": [
      {"math_round": 2}
    ]
  }
}

Payload out

{"unit_tax": 2.6}

*ppk_tracked*

Reads a value like *ppk* and, as a side effect, records it against the entity HighCohesion tracks for this event (for example the order or product). This is how the platform remembers which source records have been seen and what ID they were given in the destination, and it is what key_lookup and col_lookup search later.

The inner block is a normal *ppk* definition with an extra *tracked_field* option that says which entity field(s) the value should be stored in.

Options

  • *ppk* — Path to the value to read and track.

  • *tracked_field* — Entity field or list of fields to store the value in: s_id (source ID), s_pid (source parent ID), d_id (destination ID), d_pid (destination parent ID) or name (a reference that is the same in both systems, such as an order number).

  • *post_format* — Optional list of post formatting functions, typically key_lookup.

Track the order number as the source ID and name

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "order_number": {
    "*ppk_tracked*": {
      "*ppk*": "order.name",
      "*tracked_field*": ["s_id", "name"]
    }
  }
}

Payload out

{"order_number": "#1001"}

Abort if the order has been seen before

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "order_number": {
    "*ppk_tracked*": {
      "*ppk*": "order.name",
      "*tracked_field*": ["s_id", "name"],
      "*post_format*": [
        {
          "key_lookup": {
            "*pluck*": "d_id",
            "*on_match*": "abort",
            "*on_fail*": "ppk",
            "*abort_message*": "Order already sent to the destination"
          }
        }
      ]
    }
  }
}

Payload out

{"order_number": "#1001"}

*ppk_extra_tracked*

Tracks a child entity linked to the event's main entity, for example the line items of an order or the variants of a product. Each call creates or updates a sub-entity whose parent is the entity tracked by *ppk_tracked*, and the field outputs the sub-entity's internal ID.

This is an advanced option that is normally set up by the HighCohesion team.

Options

  • *ppk* — Path to the value to read and track.

  • *tracked_field* — Entity field(s) to store the value in, as for *ppk_tracked*.

  • *tracked_data_type* — Optional. Data type of the sub-entity. Defaults to the stream's data type.

  • *field_only* — Optional. When present, updates the most recently created sub-entity instead of searching for one, so several fields can be written to the same sub-entity.

Example

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "lines": {
    "*list*": "order.line_items",
    "*list_fields*": {
      "line_id": {
        "*ppk_extra_tracked*": {
          "*ppk*": "sku",
          "*tracked_field*": ["s_id", "name"],
          "*tracked_data_type*": "order_line"
        }
      },
      "sku": {"*ppk*": "sku"}
    }
  }
}

Payload out

{
  "lines": [
    {"line_id": "64f1c0ffee0000000000abcd", "sku": "TSHIRT-M"},
    {"line_id": "64f1c0ffee0000000000abce", "sku": "CAP-01"}
  ]
}

*stream_setting*

Reads a value from the stream's settings in the Control Panel. Settings are looked up first in the destination's additional settings and then in the stream's own additional settings. If the key is not found in either, the value no_valid_setting_found is output.

This lets one transformation file serve several streams that differ only in a few values, such as a warehouse code or a price list ID.

Options

  • *stream_setting* — The setting key to read.

Example

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "warehouse": {"*stream_setting*": "warehouse_id"}
}

Stream settings

{"warehouse_id": "ROTH001"}

Payload out

{"warehouse": "ROTH001"}

*message_data*

Reads a value from the event message rather than the payload, for example the stream title or the event ID. Useful for adding a reference to the output that identifies where the record came from.

Options

  • *message_data* — Dotted path into the event message. Commonly used paths are stream.spec.title, stream.spec.id and event.id.

  • *post_format* — Optional list of post formatting functions.

Example

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "stream_name": {"*message_data*": "stream.spec.title"},
  "event_id": {"*message_data*": "event.id"}
}

Payload out

{"stream_name": "Orders: Shopify to NetSuite", "event_id": "evt1"}

*stored_value*

Outputs a value that was saved earlier in the same transformation with the store_value post formatting function. Values are stored per event, so this is a way to reuse a computed value in several places, or to lift a value out of a list to the top level.

If nothing has been stored under the key the field is output as an empty string. Fields are processed in file order, so the store_value must appear before the *stored_value*.

Options

  • *stored_value* — The key used in store_value.

  • *post_format* — Optional list of post formatting functions.

Example

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "--order_ref": {
    "*ppk*": "order.name",
    "*post_format*": [
      {
        "replace": {"find": "#", "replace": ""}
      },
      {"prefix": "WEB-"},
      {
        "store_value": {"key": "order_ref"}
      }
    ]
  },
  "header": {
    "reference": {"*stored_value*": "order_ref"}
  },
  "lines": {
    "*list*": "order.line_items",
    "*list_fields*": {
      "reference": {"*stored_value*": "order_ref"},
      "sku": {"*ppk*": "sku"}
    }
  }
}

Payload out

{
  "header": {"reference": "WEB-1001"},
  "lines": [
    {"reference": "WEB-1001", "sku": "TSHIRT-M"},
    {"reference": "WEB-1001", "sku": "CAP-01"}
  ]
}

The --order_ref field is a hidden field: it is evaluated but not written to the output.

*counter*

Outputs an incrementing integer. The counter starts at 1 for each event and increases by one every time the same counter name is evaluated, which makes it ideal for line numbers.

Options

  • *counter* — A name for the counter. Use different names for independent counters.

Example

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "lines": {
    "*list*": "order.line_items",
    "*list_fields*": {
      "line_number": {"*counter*": "line"},
      "sku": {"*ppk*": "sku"}
    }
  }
}

Payload out

{
  "lines": [
    {"line_number": 1, "sku": "TSHIRT-M"},
    {"line_number": 2, "sku": "CAP-01"}
  ]
}

*if*

Chooses what to output based on a condition, without first reading a value with *ppk*. It takes the same options as the if post formatting function; use input to name the payload path to test.

Options

  • *if* — An if options object. See the if post formatting function for the full list of options.

Example

Payload in

{
  "shipping_lines": [
    {"code": "EXPRESS"}
  ]
}

Transformation

{
  "carrier_service": {
    "*if*": {
      "input": "shipping_lines.0.code",
      "expression": "==",
      "value": "EXPRESS",
      "then": [
        {"static_value": "DPD Next Day"}
      ],
      "else": [
        {"static_value": "DPD Standard"}
      ]
    }
  }
}

Payload out

{"carrier_service": "DPD Next Day"}

Hidden fields (--)

Any output key that starts with -- is evaluated but not written to the payload out. Use this to run side effects such as store_value or *ppk_tracked* without adding a key to the destination payload.

Example

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "--track": {
    "*ppk_tracked*": {
      "*ppk*": "order.name",
      "*tracked_field*": ["s_id", "name"]
    }
  },
  "reference": {"*ppk*": "order.name"}
}

Payload out

{"reference": "#1001"}

no_transform

If the transformation file contains a top-level key called no_transform (with an empty object as its value), the payload in is passed through to the destination unchanged. Any other keys in the file are still evaluated (so tracking still happens) but their output is discarded.

Example

Payload in

{"name": "#1001", "total": "53.45"}

Transformation

{
  "no_transform": {},
  "--track": {
    "*ppk_tracked*": {
      "*ppk*": "name",
      "*tracked_field*": ["s_id", "name"]
    }
  }
}

Payload out

{"name": "#1001", "total": "53.45"}

Lists

Most payloads contain repeating data: the line items of an order, a batch of stock levels, the addresses on a customer. A list definition tells the transformer to loop over a list in the payload in and produce a list in the payload out. Inside the loop, *ppk* paths are relative to the current item.

*list* and *list_fields*

*list* names the list in the payload in to loop over, and *list_fields* describes the object to build for each item. The output is a list of those objects.

If the path does not resolve to a non-empty list, the output is an empty object and a warning is logged.

Options

  • *list* — Path to the list in the payload in.

  • *list_fields* — A transformation block applied to each item of the list.

  • *enforce_list* — Optional. When present, a single object at the path is wrapped in a list so it is processed as one item. Useful for XML-derived payloads where a one-item list arrives as an object.

  • *list_post_format* — Optional list of list post formatting functions applied to the finished list.

Example 1

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "order_number": {"*ppk*": "order.name"},
  "lines": {
    "*list*": "order.line_items",
    "*list_fields*": {
      "sku": {"*ppk*": "sku"},
      "qty": {"*ppk*": "quantity"},
      "unit_price": {
        "*ppk*": "price",
        "*post_format*": [
          {"cast": "float"}
        ]
      }
    }
  }
}

Payload out

{
  "order_number": "#1001",
  "lines": [
    {"sku": "TSHIRT-M", "qty": 2, "unit_price": 19.5},
    {"sku": "CAP-01", "qty": 1, "unit_price": 9.5}
  ]
}

Using *enforce_list* when the source sends one item as an object

Payload in

{
  "shipment": {
    "parcel": {"tracking": "JD0001"}
  }
}

Transformation

{
  "parcels": {
    "*list*": "shipment.parcel",
    "*enforce_list*": true,
    "*list_fields*": {
      "tracking_number": {"*ppk*": "tracking"}
    }
  }
}

Payload out

{
  "parcels": [
    {"tracking_number": "JD0001"}
  ]
}

*list_field*

The singular form of *list_fields*. Instead of building an object per item it outputs one value per item, giving a flat list of values.

Options

  • *list* — Path to the list in the payload in.

  • *list_field* — A single field definition applied to each item.

Example

Payload in

{
  "fulfillment": {
    "tracking_numbers": [
      {"code": "JD0001"},
      {"code": "JD0002"}
    ]
  }
}

Transformation

{
  "tracking_numbers": {
    "*list*": "fulfillment.tracking_numbers",
    "*list_field*": {"*ppk*": "code"}
  }
}

Payload out

{
  "tracking_numbers": ["JD0001", "JD0002"]
}

*list_count*

Outputs the number of items in a list.

Options

  • *list_count* — Path to the list.

  • *post_format* — Optional list of post formatting functions.

Example

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "total_lines": {"*list_count*": "order.line_items"}
}

Payload out

{"total_lines": 2}

*list_combine*

Builds several lists and concatenates them into one. The value is a transformation block whose keys each produce a list; the lists are joined in key order.

Options

  • *list_combine* — A transformation block where each key is a *list* definition.

Example

Payload in

{
  "billing_address": {"city": "Bristol"},
  "shipping_addresses": [
    {"city": "Bath"},
    {"city": "Cardiff"}
  ]
}

Transformation

{
  "addresses": {
    "*list_combine*": {
      "billing": {
        "*list*": "billing_address",
        "*enforce_list*": true,
        "*list_fields*": {
          "type": {"*static_value*": "billing"},
          "city": {"*ppk*": "city"}
        }
      },
      "shipping": {
        "*list*": "shipping_addresses",
        "*list_fields*": {
          "type": {"*static_value*": "shipping"},
          "city": {"*ppk*": "city"}
        }
      }
    }
  }
}

Payload out

{
  "addresses": [
    {"type": "billing", "city": "Bristol"},
    {"type": "shipping", "city": "Bath"},
    {"type": "shipping", "city": "Cardiff"}
  ]
}

Pre-formatting

Pre-formatting functions reshape the payload in before any fields are mapped. They are listed under a top-level *pre_format* key and run in order; each one receives the whole payload and returns the modified payload.

*pre_format* must be at the top level of the transformation file.

array_check

Makes sure a path holds a list. If the element at check_array_element exists the payload is returned unchanged; otherwise the value at take_array_element is removed and re-inserted under new_array_key wrapped in a list. Use this when a source sends a single object where a list is expected.

The function only rewrites the top level of the payload. For a nested path, move the result to the root with new_array_key as shown in the second example.

Options

  • check_array_element — Path that should exist if the data is already a list, typically the existing path with .0 appended.

  • take_array_element — Path of the object to wrap when the check fails.

  • new_array_key — Top-level key to write the new list to.

Example 1

Payload in

{
  "shippingAddress": {"firstName": "Jonas", "lastName": "Munk"}
}

Transformation

{
  "*pre_format*": [
    {
      "array_check": {
        "check_array_element": "shippingAddress.0",
        "take_array_element": "shippingAddress",
        "new_array_key": "shippingAddress"
      }
    }
  ],
  "addresses": {
    "*list*": "shippingAddress",
    "*list_fields*": {
      "first_name": {"*ppk*": "firstName"}
    }
  }
}

Payload out

{
  "addresses": [
    {"first_name": "Jonas"}
  ]
}

Nested object moved to the root

Payload in

{
  "shippingAddress": {
    "node": {
      "addresses": {"phone": "12345678780"}
    }
  }
}

Transformation

{
  "*pre_format*": [
    {
      "array_check": {
        "check_array_element": "shippingAddress.node.addresses.0",
        "take_array_element": "shippingAddress.node.addresses",
        "new_array_key": "addresses"
      }
    }
  ],
  "phones": {
    "*list*": "addresses",
    "*list_fields*": {
      "phone": {"*ppk*": "phone"}
    }
  }
}

Payload out

{
  "phones": [
    {"phone": "12345678780"}
  ]
}

group_on

Groups the items of a flat list by the value of one key. The payload in must be a list. The output is an object with a single key (index) holding one entry per distinct value, each with a group list of the original items in order of first appearance.

This is most useful for CSV sources, where child rows arrive flattened and need to be re-nested under their parent.

Options

  • key — The key in each item to group by.

  • index — The name of the list in the reshaped payload.

Example

Payload in

[  {"barcode": "1234", "qty": 1},  {"barcode": "5678", "qty": 2},  {"barcode": "1234", "qty": 3}]

Transformation

{
  "*pre_format*": [
    {
      "group_on": {"key": "barcode", "index": "products"}
    }
  ],
  "products": {
    "*list*": "products",
    "*list_fields*": {
      "barcode": {"*ppk*": "group.0.barcode"},
      "qty": {
        "*static_value*": 0,
        "*post_format*": [
          {
            "sum_list_key": {"list": "group", "key": "qty"}
          }
        ]
      }
    }
  }
}

Payload out

{
  "products": [
    {"barcode": "1234", "qty": 4.0},
    {"barcode": "5678", "qty": 2.0}
  ]
}

After grouping, the payload in becomes {"products": [{"group": [...]}, {"group": [...]}]}. Each group holds the original rows, so sum_list_key can total the quantities.

merge_up

Flattens a nested list up to its parent: each child item becomes its own row that also carries a copy of the parent (minus the child list). This is the opposite of group_on and is useful for building flat files such as CSV, where every line item row needs the order header repeated.

The option is a single string of five words: <list> as <parent_key> with <child_list>. Only the first, third and fifth words are read, so as and with are just for readability.

Options

  • merge_up — String in the form orders as order with line_items: loop orders, copy each order under order, and merge in each of its line_items.

Example

Payload in

{
  "orders": [
    {
      "name": "#1001",
      "line_items": [
        {"sku": "TSHIRT-M", "quantity": 2},
        {"sku": "CAP-01", "quantity": 1}
      ]
    }
  ]
}

Transformation

{
  "*pre_format*": [
    {"merge_up": "orders as order with line_items"}
  ],
  "rows": {
    "*list*": "orders",
    "*list_fields*": {
      "order_number": {"*ppk*": "order.name"},
      "sku": {"*ppk*": "sku"},
      "qty": {"*ppk*": "quantity"}
    }
  }
}

Payload out

{
  "rows": [
    {"order_number": "#1001", "sku": "TSHIRT-M", "qty": 2},
    {"order_number": "#1001", "sku": "CAP-01", "qty": 1}
  ]
}

unset_key

Removes items from a list in the payload in where a field matches a condition. Everything else is left as it is.

Options

  • key — Path to the list to filter.

  • field — Path within each item to test.

  • expression — Comparison operator. Any operator supported by if can be used: ==, <>, >, <, >=, <=, in, contains, does not contain, starts with, ends with. Defaults to ==.

  • value — Value to compare against. Items where the test is true are removed.

Example

Payload in

{
  "order": {
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2},
      {"sku": "GIFT-WRAP", "quantity": 1}
    ]
  }
}

Transformation

{
  "*pre_format*": [
    {
      "unset_key": {
        "key": "order.line_items",
        "field": "sku",
        "expression": "starts with",
        "value": "GIFT"
      }
    }
  ],
  "lines": {
    "*list*": "order.line_items",
    "*list_fields*": {
      "sku": {"*ppk*": "sku"},
      "qty": {"*ppk*": "quantity"}
    }
  }
}

Payload out

{
  "lines": [
    {"sku": "TSHIRT-M", "qty": 2}
  ]
}

Post formatting

Post formatting functions change a value after it has been read from the payload in. They are listed under a *post_format* key inside a field and run in order, each one receiving the output of the previous one. Most take a single option (a string, number or true); some take an object.

If a function fails (for example cast to int on a non-numeric string) a warning is logged and the value is passed on unchanged. The exceptions are if with then: "error", and lookups with *on_fail*: "error", which fail the event.

The functions are listed alphabetically.

absolute

Returns the absolute value of a number. Strings are returned unchanged.

Options

  • (value) — No options. Pass true.

Example

Payload in

{"total_discount": -4.5}

Transformation

{
  "discount": {
    "*ppk*": "total_discount",
    "*post_format*": [
      {"absolute": true}
    ]
  }
}

Payload out

{"discount": 4.5}

add_check_digit

Appends the EAN/UPC check digit to a 12-digit code, producing a 13-digit code. Values that are not exactly 12 characters long are returned unchanged.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "product": {"upc": "111456749112"}
}

Transformation

{
  "ean": {
    "*ppk*": "product.upc",
    "*post_format*": [
      {"add_check_digit": true}
    ]
  }
}

Payload out

{"ean": "1114567491122"}

add_key_to_list

Wraps every item of a list in an object under the given key. Commonly used after expand to turn a comma-separated string into a list of objects.

Options

  • (value) — The key to wrap each item in.

Example

Payload in

{
  "product": {
    "images": "https://cdn.example.com/a.jpg,https://cdn.example.com/b.jpg"
  }
}

Transformation

{
  "images": {
    "*ppk*": "product.images",
    "*post_format*": [
      {"expand": ","},
      {"add_key_to_list": "src"}
    ]
  }
}

Payload out

{
  "images": [
    {"src": "https://cdn.example.com/a.jpg"},
    {"src": "https://cdn.example.com/b.jpg"}
  ]
}

bleckmann_character_replace

Cleans a string for the Bleckmann WMS: accented characters are transliterated (see replace_accent_character), & becomes and, and the characters < > . ; plus line breaks are removed. Curly apostrophes become straight ones. When applied to an object, every value in it is cleaned.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "billing_address": {"company": "Smith & Sons; Ltd."}
}

Transformation

{
  "company": {
    "*ppk*": "billing_address.company",
    "*post_format*": [
      {"bleckmann_character_replace": true}
    ]
  }
}

Payload out

{"company": "Smith and Sons Ltd"}

calculate

Evaluates an arithmetic expression held in a string. Supports + - * / and brackets. Usually paired with ppk_replace to substitute payload values into a formula first.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "grand_total": "53.45",
  "shipping_amount": "4.95",
  "subtotal": "40.00"
}

Transformation

{
  "tax": {
    "*static_value*": "{total} - {shipping} - {subtotal}",
    "*post_format*": [
      {
        "ppk_replace": {
          "{total}": "grand_total",
          "{shipping}": "shipping_amount",
          "{subtotal}": "subtotal"
        }
      },
      {"calculate": true},
      {"math_round": 2}
    ]
  }
}

Payload out

{"tax": 8.5}

camel_case

Converts a space-separated phrase to camelCase.

Options

  • (value) — No options. Pass true.

Example

Payload in

{"label": "shipping address country"}

Transformation

{
  "field_name": {
    "*ppk*": "label",
    "*post_format*": [
      {"camel_case": true}
    ]
  }
}

Payload out

{"field_name": "shippingAddressCountry"}

camel_case_to_sentence

Converts a camelCase string to a sentence: a space is inserted before each capital letter and the first letter is capitalised.

Options

  • (value) — No options. Pass true.

Example

Payload in

{"field": "shippingAddressCountry"}

Transformation

{
  "label": {
    "*ppk*": "field",
    "*post_format*": [
      {"camel_case_to_sentence": true}
    ]
  }
}

Payload out

{"label": "Shipping Address Country"}

cast

Converts the value to another type. bool follows Python rules: any non-empty string is true, including "0" and "false"; use if for a string-based flag.

Options

  • (value) — Target type: int, float, str, bool, ord, hex or oct. Unknown types fall back to str.

Example

Payload in

{"qty_ordered": "3", "price": "19.50", "id": 1001}

Transformation

{
  "quantity": {
    "*ppk*": "qty_ordered",
    "*post_format*": [
      {"cast": "int"}
    ]
  },
  "unit_price": {
    "*ppk*": "price",
    "*post_format*": [
      {"cast": "float"}
    ]
  },
  "external_id": {
    "*ppk*": "id",
    "*post_format*": [
      {"cast": "str"}
    ]
  }
}

Payload out

{"quantity": 3, "unit_price": 19.5, "external_id": "1001"}

col_lookup

Looks up a tracked entity by any of its columns and returns another column from it. Where key_lookup always matches on the entity's tracked ID for the current stream's data type, col_lookup lets you name the data type and the column to match on, so it can find entities tracked by other streams, for example resolving a SKU to the destination product ID that the product stream recorded.

Options

  • *match* — Column to match the current value against: s_id, s_pid, d_id, d_pid, name, or any other entity field.

  • *pluck* — Column to return, using the same names.

  • *data_type* — Entity data type to search, for example product or order.

  • *sort_by* — Optional. updated_at or created_at, to pick the most recent match when several exist.

  • *status* — Optional. When present, a match without a destination ID is treated as not found.

  • *on_fail* — What to do when nothing is found: empty (output ""), ppk (keep the current value), abort (stop the event silently), error (fail the event), or any other string to output that string.

  • *abort_message* — Optional message recorded when *on_fail* is abort.

Resolve a SKU to the destination product ID

Payload in

{"sku": "TSHIRT-M"}

Transformation

{
  "variant_id": {
    "*ppk*": "sku",
    "*post_format*": [
      {
        "col_lookup": {
          "*match*": "name",
          "*pluck*": "d_id",
          "*data_type*": "product",
          "*on_fail*": "empty"
        }
      }
    ]
  }
}

Tracked entities

[  {    "data_type": "product",    "name": "TSHIRT-M",    "source_id": "gid://shopify/ProductVariant/4471",    "destination_id": "NS-4471"  }]

Payload out

{"variant_id": "NS-4471"}

Abort when the record has already been sent

Payload in

{"sku": "TSHIRT-M"}

Transformation

{
  "variant_id": {
    "*ppk*": "sku",
    "*post_format*": [
      {
        "col_lookup": {
          "*match*": "name",
          "*pluck*": "d_id",
          "*data_type*": "product",
          "*on_fail*": "abort",
          "*abort_message*": "Product not yet created in the destination"
        }
      }
    ]
  }
}

Tracked entities (none)

Payload out

No payload out. The event is aborted with the message “Product not yet created in the destination”.

With no matching entity the event is aborted and the abort message is shown against the event in the Control Panel.

country_code_to_netsuite_enum

Converts an ISO 3166-1 alpha-2 country code to the enum value NetSuite expects, for example GB to _unitedKingdom. Unknown codes are returned unchanged.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "shipping_address": {"country_code": "GB"}
}

Transformation

{
  "country": {
    "*ppk*": "shipping_address.country_code",
    "*post_format*": [
      {"country_code_to_netsuite_enum": true}
    ]
  }
}

Payload out

{"country": "_unitedKingdom"}

current_list_item_fallback

If the value is empty, reads another path from the current list item instead. Only meaningful inside a *list*. Compare fallback, which reads from the root of the payload.

Options

  • (value) — Path within the current list item to fall back to.

Example

Payload in

{
  "line_items": [
    {"sku": "TSHIRT-M", "barcode": "5012345678900"},
    {"sku": "", "barcode": "5012345678917"}
  ]
}

Transformation

{
  "lines": {
    "*list*": "line_items",
    "*list_fields*": {
      "item_ref": {
        "*ppk*": "sku",
        "*post_format*": [
          {"current_list_item_fallback": "barcode"}
        ]
      }
    }
  }
}

Payload out

{
  "lines": [
    {"item_ref": "TSHIRT-M"},
    {"item_ref": "5012345678917"}
  ]
}

current_timestamp

Replaces the value with the current Unix timestamp in seconds. Chain date_format with input: "%s" to format it.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "order": {"name": "#1001"}
}

Transformation

{
  "exported_at": {
    "*static_value*": "",
    "*post_format*": [
      {"current_timestamp": true},
      {
        "date_format": {"input": "%s", "output": "%Y-%m-%d %H:%M:%S"}
      }
    ]
  }
}

Payload out

{"exported_at": "2026-09-11 08:15:42"}

date_format

Parses a date or datetime string and writes it out in another format, optionally converting between time zones or shifting it by a fixed number of seconds. Format strings use Python strftime codes (%Y year, %m month, %d day, %H:%M:%S time, %z offset).

If the value cannot be parsed with input, the transformer strips - T : / from it and tries to read the first 12 characters as YYYYMMDDHHMMSS.

Options

  • input — Format of the incoming value, or %s for a Unix timestamp in seconds.

  • output — Format to write, or UNIX for a Unix timestamp in seconds, or UNIX13 for milliseconds.

  • input_timezone — Optional. Time zone the incoming value is in when it has no offset of its own. Currently only utc is supported.

  • output_timezone — Optional. IANA time zone to convert to, for example Europe/London.

  • timedelta — Optional. Seconds to add (or subtract, if negative) to the parsed date. Not applied to UNIX outputs.

  • iso_format_with_tz — Optional. IANA time zone; when present the output is an ISO 8601 string with that zone's offset, and output is ignored.

Change the format

Payload in

{"created_at": "2026-07-14T09:05:00Z"}

Transformation

{
  "order_date": {
    "*ppk*": "created_at",
    "*post_format*": [
      {
        "date_format": {"input": "%Y-%m-%dT%H:%M:%SZ", "output": "%d/%m/%Y"}
      }
    ]
  }
}

Payload out

{"order_date": "14/07/2026"}

Convert UTC to UK local time

Payload in

{"created_at": "2026-07-14T09:05:00Z"}

Transformation

{
  "order_date": {
    "*ppk*": "created_at",
    "*post_format*": [
      {
        "date_format": {
          "input": "%Y-%m-%dT%H:%M:%SZ",
          "input_timezone": "utc",
          "output": "%Y-%m-%d %H:%M:%S",
          "output_timezone": "Europe/London"
        }
      }
    ]
  }
}

Payload out

{"order_date": "2026-07-14 10:05:00"}

Shift by 5 minutes and output a Unix timestamp

Payload in

{"created_at": "2026-07-14T09:05:00Z"}

Transformation

{
  "due_at": {
    "*ppk*": "created_at",
    "*post_format*": [
      {
        "date_format": {
          "input": "%Y-%m-%dT%H:%M:%SZ",
          "output": "%Y-%m-%dT%H:%M:%S",
          "timedelta": 300
        }
      }
    ]
  },
  "created_unix": {
    "*ppk*": "created_at",
    "*post_format*": [
      {
        "date_format": {
          "input": "%Y-%m-%dT%H:%M:%SZ",
          "input_timezone": "utc",
          "output": "UNIX"
        }
      }
    ]
  }
}

Payload out

{"due_at": "2026-07-14T09:10:00", "created_unix": 1784019900.0}

do_nothing

Returns the value unchanged. Used as a placeholder in an if branch where one side should leave the value alone.

Options

  • (value) — No options. Pass true.

Example

Payload in

{"financial_status": "pending"}

Transformation

{
  "status": {
    "*ppk*": "financial_status",
    "*post_format*": [
      {
        "if": {
          "expression": "==",
          "value": "paid",
          "then": [
            {"static_value": "RELEASED"}
          ],
          "else": [
            {"do_nothing": true}
          ]
        }
      }
    ]
  }
}

Payload out

{"status": "pending"}

expand

Splits a string into a list on a separator. The opposite of squash.

Options

  • (value) — The separator to split on.

Example

Payload in

{"tags": "wholesale, priority, gift"}

Transformation

{
  "tags": {
    "*ppk*": "tags",
    "*post_format*": [
      {"expand": ", "}
    ]
  }
}

Payload out

{
  "tags": ["wholesale", "priority", "gift"]
}

fallback

If the value is empty ("" or null), reads another path from the root of the payload in instead. Inside a list, use current_list_item_fallback to read from the current item.

Options

  • (value) — Path in the payload in to fall back to.

Example

Payload in

{
  "customer": {"first_name": ""},
  "billing_address": {"first_name": "Joe"}
}

Transformation

{
  "first_name": {
    "*ppk*": "customer.first_name",
    "*post_format*": [
      {"fallback": "billing_address.first_name"}
    ]
  }
}

Payload out

{"first_name": "Joe"}

format_numeric_str

Formats a number using a Python format string. The value is cast to a float first and is available as {0}.

Options

  • (value) — Format string, for example {0:.2f} for two decimal places or £{0:,.2f} for a thousands separator.

Example

Payload in

{"price": 12.0222222}

Transformation

{
  "price_label": {
    "*ppk*": "price",
    "*post_format*": [
      {"format_numeric_str": "{0:.2f}"}
    ]
  }
}

Payload out

{"price_label": "12.02"}

get_increment

Replaces the value with the next number from a HighCohesion-managed sequence. The sequence is shared across all events and streams that use the same key, so it can generate unique, ever-increasing document numbers.

Options

  • universal_key — Name of the sequence. Use a unique key per document type and organisation.

Example

Payload in

{
  "order": {"name": "#1001"}
}

Transformation

{
  "document_number": {
    "*static_value*": "0",
    "*post_format*": [
      {
        "get_increment": {"universal_key": "acme_sales_orders"}
      }
    ]
  }
}

Payload out

{"document_number": 1043}

get_lead_zero

Left-pads the value with zeros to a total length.

Options

  • (value) — Total length of the output string.

Example

Payload in

{"id": 52645}

Transformation

{
  "order_number": {
    "*ppk*": "id",
    "*post_format*": [
      {"get_lead_zero": 8}
    ]
  }
}

Payload out

{"order_number": "00052645"}

get_value_from_dic

When the current value is an object, reads one key from it. Usually chained after stream_setting_lookup or json_to_array.

Options

  • key — Path to read from the object.

Example

Payload in

{
  "shipping_line": {"code": "EXPRESS"}
}

Transformation

{
  "carrier_code": {
    "*ppk*": "shipping_line.code",
    "*post_format*": [
      {
        "stream_setting_lookup": {"get_key_from": "output"}
      },
      {
        "get_value_from_dic": {"key": "carrier"}
      }
    ]
  }
}

Stream settings

{
  "EXPRESS": {"carrier": "DPD", "service": "12"}
}

Payload out

{"carrier_code": "DPD"}

if

Tests a condition and runs one of two lists of post formatting functions, or drops, aborts or fails the event. By default the current value is tested against value; use input to test a different path from the payload instead, and ppk_input to compare against a value read from the payload rather than a literal.

then and else each accept either a list of post formatting functions to run on the value, or one of three keywords: drop_block removes the field from the output entirely, abort stops the event without an error, and error fails the event with a message.

Options

  • expression — One of ==, <>, >, <, >=, <=, in, contains, does not contain, starts with, ends with. Numeric comparisons accept numeric strings and treat a comma as a decimal point.

  • value — Value to compare against. For in, a list.

  • then — List of functions, or drop_block, abort, error.

  • else — Optional. Same options as then. When omitted and the test fails, the value is unchanged.

  • input — Optional. Path in the payload to test instead of the current value.

  • ppk_input — Optional. Path in the payload whose value replaces value.

  • value_current_date — Optional. Replaces value with the current date: UNIX for a timestamp, or a strftime format string.

  • key_type_value — Optional. Where input, ppk_input and ppk read from: payload_in (default) or current_list_item.

  • abort_message — Optional. Message recorded when the outcome is abort.

  • error_message — Optional. Message recorded when the outcome is error.

Map a value

Payload in

{
  "shipping_lines": [
    {"title": "DPD Express Next Working Day Delivery"}
  ]
}

Transformation

{
  "haulier_code": {
    "*ppk*": "shipping_lines.0.title",
    "*post_format*": [
      {
        "if": {
          "expression": "==",
          "value": "DPD Express Next Working Day Delivery",
          "then": [
            {"static_value": "DPD ND"}
          ],
          "else": [
            {"static_value": "DPD 2DAY"}
          ]
        }
      }
    ]
  }
}

Payload out

{"haulier_code": "DPD ND"}

Test a different field with input

Payload in

{"financial_status": "paid", "total": "53.45"}

Transformation

{
  "amount_paid": {
    "*ppk*": "total",
    "*post_format*": [
      {
        "if": {
          "input": "financial_status",
          "expression": "==",
          "value": "paid",
          "then": [
            {"cast": "float"}
          ],
          "else": [
            {"static_value": 0}
          ]
        }
      }
    ]
  }
}

Payload out

{"amount_paid": 53.45}

Drop the field when a condition is met

Payload in

{
  "customer": {"company": ""}
}

Transformation

{
  "company": {
    "*ppk*": "customer.company",
    "*post_format*": [
      {
        "if": {"expression": "==", "value": "", "then": "drop_block"}
      }
    ]
  },
  "customer_type": {"*static_value*": "B2C"}
}

Payload out

{"customer_type": "B2C"}

Abort or fail the event

Payload in

{"tags": "test-order"}

Transformation

{
  "tags": {
    "*ppk*": "tags",
    "*post_format*": [
      {
        "if": {
          "expression": "contains",
          "value": "test-order",
          "then": "abort",
          "abort_message": "Test orders are not sent to the ERP"
        }
      }
    ]
  }
}

Payload out

No payload out. The event is aborted with the message “Test orders are not sent to the ERP”.

Use then: "error" with error_message instead of abort when the event should be flagged as failed.

iso2_to_iso3

Converts an ISO 3166-1 alpha-2 country code (GB) to alpha-3 (GBR). Unknown codes are returned unchanged.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "billing_address": {"country_code": "GB"}
}

Transformation

{
  "country": {
    "*ppk*": "billing_address.country_code",
    "*post_format*": [
      {"iso2_to_iso3": true}
    ]
  }
}

Payload out

{"country": "GBR"}

iso2_to_name

Converts an ISO alpha-2 country code to the official short country name.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "billing_address": {"country_code": "DE"}
}

Transformation

{
  "country": {
    "*ppk*": "billing_address.country_code",
    "*post_format*": [
      {"iso2_to_name": true}
    ]
  }
}

Payload out

{"country": "Germany"}

iso3_to_iso2

Converts an ISO alpha-3 country code (GBR) to alpha-2 (GB).

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "billing_address": {"country": "FRA"}
}

Transformation

{
  "country": {
    "*ppk*": "billing_address.country",
    "*post_format*": [
      {"iso3_to_iso2": true}
    ]
  }
}

Payload out

{"country": "FR"}

iso3_to_name

Converts an ISO alpha-3 country code to the official short country name.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "billing_address": {"country": "NLD"}
}

Transformation

{
  "country": {
    "*ppk*": "billing_address.country",
    "*post_format*": [
      {"iso3_to_name": true}
    ]
  }
}

Payload out

{"country": "Netherlands"}

json

Parses a JSON string held in the value and reads one path from the result. Useful for sources that store structured data in a single text field, such as Shopify note attributes.

Options

  • key — Path to read from the parsed JSON.

Example

Payload in

{"order_options_json": "{\"lang\": \"fr\", \"gift\": true}"}

Transformation

{
  "language": {
    "*ppk*": "order_options_json",
    "*post_format*": [
      {
        "json": {"key": "lang"}
      }
    ]
  }
}

Payload out

{"language": "fr"}

json_to_array

Parses a JSON string into an object or list so later functions (or the destination) receive structured data instead of text.

Options

  • (value) — No options. Pass true.

Example

Payload in

{"order_options_json": "[\"gift_wrap\", \"express\"]"}

Transformation

{
  "options": {
    "*ppk*": "order_options_json",
    "*post_format*": [
      {"json_to_array": true}
    ]
  }
}

Payload out

{
  "options": ["gift_wrap", "express"]
}

key_lookup

Looks up the entity that HighCohesion tracked for the current value (see *ppk_tracked*) and returns one of its columns, typically the destination ID. This is how a stream finds out whether a record has already been sent and what ID the destination gave it, so it can update instead of create, skip duplicates, or switch to a different transformation file.

Options

  • *pluck* — Column to return: s_id, s_pid, d_id, d_pid or name.

  • *data_type* — Optional. Entity data type to search. Defaults to the stream's data type.

  • *on_fail* — What to do when nothing is found: empty, ppk (keep the current value), abort, error, or any other string to output literally.

  • *on_match* — Optional. abort stops the event when a match is found (duplicate protection). transformation_switch continues the event with the transformation file named in *transformation_id*.

  • *transformation_id* — ID of the transformation to switch to when *on_match* is transformation_switch.

  • *on_pending* — Optional. When present and nothing is found, also abort if another event for the same entity is still pending in the destination.

  • *abort_message* — Optional message recorded on abort.

Update if already sent, otherwise leave blank for a create

Payload in

{"sku": "TSHIRT-M"}

Transformation

{
  "id": {
    "*ppk_tracked*": {
      "*ppk*": "sku",
      "*tracked_field*": ["s_id", "name"],
      "*post_format*": [
        {
          "key_lookup": {"*pluck*": "d_id", "*on_fail*": "empty"}
        }
      ]
    }
  }
}

Tracked entities

[  {    "data_type": "order",    "source_id": "TSHIRT-M",    "name": "TSHIRT-M",    "destination_id": "NS-4471"  }]

Payload out

{"id": "NS-4471"}

Switch transformation file when the record already exists

Payload in

{"sku": "TSHIRT-M"}

Transformation

{
  "id": {
    "*ppk_tracked*": {
      "*ppk*": "sku",
      "*tracked_field*": ["s_id", "name"],
      "*post_format*": [
        {
          "key_lookup": {
            "*pluck*": "d_id",
            "*on_fail*": "empty",
            "*on_match*": "transformation_switch",
            "*transformation_id*": "ef755f7a-bdcc-11e9-8692-366c3ae2703e"
          }
        }
      ]
    }
  }
}

Tracked entities (none)

Payload out

{"id": ""}

Here no entity exists yet, so the value is empty and the current file continues. On a later run the match is found and the rest of the event is processed with the update transformation instead.

length_value

Replaces the value with its length (characters of a string, or items of a list).

Options

  • (value) — No options. Pass true.

Example

Payload in

{"description": "Organic cotton tee"}

Transformation

{
  "description_length": {
    "*ppk*": "description",
    "*post_format*": [
      {"length_value": true}
    ]
  }
}

Payload out

{"description_length": 18}

lowercase

Converts a string to lower case. Non-strings are returned unchanged.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "customer": {"email": "Joe.Bloggs@Example.com"}
}

Transformation

{
  "email": {
    "*ppk*": "customer.email",
    "*post_format*": [
      {"lowercase": true}
    ]
  }
}

Payload out

{"email": "joe.bloggs@example.com"}

ltrim

Removes the given characters from the start of a string.

Options

  • (value) — Characters to strip, for example " " or "0".

Example

Payload in

{"order_ref": "000052645"}

Transformation

{
  "order_number": {
    "*ppk*": "order_ref",
    "*post_format*": [
      {"ltrim": "0"}
    ]
  }
}

Payload out

{"order_number": "52645"}

math

Applies one arithmetic operation with a fixed number, or with a number read from the payload. The current value is cast to a float. Division by zero returns the value unchanged.

Options

  • operator+, -, * or /.

  • value — Number to apply.

  • value_ppk — Optional. Path in the payload in whose value is used instead of value.

Example

Payload in

{"price": "19.50", "exchange_rate": 1.17}

Transformation

{
  "price_inc_vat": {
    "*ppk*": "price",
    "*post_format*": [
      {
        "math": {"operator": "*", "value": 1.2}
      },
      {"math_round": 2}
    ]
  },
  "price_eur": {
    "*ppk*": "price",
    "*post_format*": [
      {
        "math": {"operator": "*", "value_ppk": "exchange_rate"}
      },
      {"math_round": 2}
    ]
  }
}

Payload out

{"price_inc_vat": 23.4, "price_eur": 22.81}

math_round

Rounds a number to the given number of decimal places.

Options

  • (value) — Number of decimal places.

Example

Payload in

{
  "billing": {"price": 10.3333}
}

Transformation

{
  "price": {
    "*ppk*": "billing.price",
    "*post_format*": [
      {"math_round": 2}
    ]
  }
}

Payload out

{"price": 10.33}

max_length

Truncates a string to a maximum number of characters. Anything beyond the limit is silently dropped, so use with care on fields such as address lines.

Options

  • (value) — Maximum length.

Example

Payload in

{
  "billing_address": {"address1": "Flat 3, 12 Long Meadow Lane"}
}

Transformation

{
  "address_line_one": {
    "*ppk*": "billing_address.address1",
    "*post_format*": [
      {"max_length": 20}
    ]
  }
}

Payload out

{"address_line_one": "Flat 3, 12 Long Mead"}

name_to_iso2

Converts an official country name (United Kingdom) to its ISO alpha-2 code (GB). The name must match the ISO short name exactly; unknown names are returned unchanged.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "billing_address": {"country": "United Kingdom"}
}

Transformation

{
  "country_code": {
    "*ppk*": "billing_address.country",
    "*post_format*": [
      {"name_to_iso2": true}
    ]
  }
}

Payload out

{"country_code": "GB"}

name_to_iso3

Converts an official country name to its ISO alpha-3 code.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "billing_address": {"country": "Ireland"}
}

Transformation

{
  "country_code": {
    "*ppk*": "billing_address.country",
    "*post_format*": [
      {"name_to_iso3": true}
    ]
  }
}

Payload out

{"country_code": "IRL"}

negative

Returns the value as a negative number (the negative of its absolute value). Strings are returned unchanged. Useful for discounts and credit notes.

Options

  • (value) — No options. Pass true.

Example

Payload in

{"total_discount": "4.50"}

Transformation

{
  "discount": {
    "*ppk*": "total_discount",
    "*post_format*": [
      {"cast": "float"},
      {"negative": true}
    ]
  }
}

Payload out

{"discount": -4.5}

netsuite_enum_to_country_code

The reverse of country_code_to_netsuite_enum: converts a NetSuite country enum such as _unitedKingdom to GB.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "shipaddress": {"country": "_unitedKingdom"}
}

Transformation

{
  "country_code": {
    "*ppk*": "shipaddress.country",
    "*post_format*": [
      {"netsuite_enum_to_country_code": true}
    ]
  }
}

Payload out

{"country_code": "GB"}

numbers_only

Removes every character except the digits 0-9.

Options

  • (value) — No options. Pass true.

Example

Payload in

{"postcode": "BS1 4DJ"}

Transformation

{
  "postcode_digits": {
    "*ppk*": "postcode",
    "*post_format*": [
      {"numbers_only": true}
    ]
  }
}

Payload out

{"postcode_digits": "14"}

pad

Adds padding characters to one side of a string. Note that length is the number of characters added, not the final length; for a fixed total width use get_lead_zero.

Options

  • sideleft or right.

  • length — Number of padding characters to add.

  • char — The padding character.

Example

Payload in

{"code": "AB12"}

Transformation

{
  "padded": {
    "*ppk*": "code",
    "*post_format*": [
      {
        "pad": {"side": "right", "length": 4, "char": "0"}
      }
    ]
  }
}

Payload out

{"padded": "AB120000"}

phone_numbers_only

Removes every character except digits and a leading +, leaving a dial-able phone number.

Options

  • (value) — No options. Pass true.

Example

Payload in

{"telephone": "+44 (0)117 123 4567"}

Transformation

{
  "phone": {
    "*ppk*": "telephone",
    "*post_format*": [
      {"phone_numbers_only": true}
    ]
  }
}

Payload out

{"phone": "+4401171234567"}

ppk

Available only inside an if branch. Replaces the value with one read from the payload in, so the two sides of a condition can take their value from different fields.

Options

  • (value) — Path in the payload in, or a list of paths joined with a space.

Example

Payload in

{
  "note_attributes": [
    {"name": "lang", "value": "fr"}
  ]
}

Transformation

{
  "language": {
    "*ppk*": "note_attributes.0.value",
    "*post_format*": [
      {
        "if": {
          "expression": "in",
          "value": ["de", "fr"],
          "then": [
            {"ppk": "note_attributes.0.value"}
          ],
          "else": [
            {"stream_setting": "default_language"}
          ]
        }
      }
    ]
  }
}

Payload out

{"language": "fr"}

ppk_is_set

Chooses between two payload paths depending on whether the current value is set. If the value is empty the false path is read, otherwise the true path.

Options

  • true — Path to read when the value is set.

  • false — Path to read when the value is empty.

Example

Payload in

{
  "customer": {"company": "", "full_name": "Joe Bloggs"}
}

Transformation

{
  "contact_name": {
    "*ppk*": "customer.company",
    "*post_format*": [
      {
        "ppk_is_set": {"true": "customer.company", "false": "customer.full_name"}
      }
    ]
  }
}

Payload out

{"contact_name": "Joe Bloggs"}

ppk_replace

Replaces placeholders in a string with values from the payload in. Each option key is the text to find and its value is the payload path to substitute. Choose placeholders that are not substrings of each other; replacements run in order, so total would also match inside subtotal. Usually chained with calculate to build formulas, or used on a *static_value* template.

Options

  • <placeholder> — One entry per placeholder: the key is the text to replace, the value is the payload path.

  • key_type — Optional. payload_in (default) or current_list_item to read paths from the current list item.

Example

Payload in

{
  "order": {"name": "#1001"},
  "customer": {"last_name": "Bloggs"}
}

Transformation

{
  "memo": {
    "*static_value*": "Web order ORDER for CUSTOMER",
    "*post_format*": [
      {
        "ppk_replace": {"ORDER": "order.name", "CUSTOMER": "customer.last_name"}
      }
    ]
  }
}

Payload out

{"memo": "Web order #1001 for Bloggs"}

prefix

Adds text to the start of the value.

Options

  • (value) — Text to prepend.

Example

Payload in

{"name": "1001"}

Transformation

{
  "order_number": {
    "*ppk*": "name",
    "*post_format*": [
      {"prefix": "UKWEB-"}
    ]
  }
}

Payload out

{"order_number": "UKWEB-1001"}

random_value

Replaces the value with a random UUID, string or integer. Use for idempotency keys or placeholder references.

Options

  • typeuuid, string (lower-case letters) or integer.

  • length — Number of characters or digits. Not used for uuid.

Example

Payload in

{
  "order": {"name": "#1001"}
}

Transformation

{
  "idempotency_key": {
    "*static_value*": "",
    "*post_format*": [
      {
        "random_value": {"type": "uuid"}
      }
    ]
  },
  "batch_ref": {
    "*static_value*": "",
    "*post_format*": [
      {
        "random_value": {"type": "string", "length": 10}
      }
    ]
  },
  "pin": {
    "*static_value*": "",
    "*post_format*": [
      {
        "random_value": {"type": "integer", "length": 6}
      }
    ]
  }
}

Payload out

{
  "idempotency_key": "49c7d4fb-7000-4a8d-bfe4-10b83362e895",
  "batch_ref": "dekalstlsa",
  "pin": 482915
}

regex

Extracts the parts of a string that match a regular expression and joins them together. It does not validate; if nothing matches the result is an empty string.

Options

  • pattern — Python regular expression.

Example

Payload in

{"commodity_code": "HS 6109.10"}

Transformation

{
  "commodity_code": {
    "*ppk*": "commodity_code",
    "*post_format*": [
      {
        "regex": {"pattern": "[0-9]+"}
      }
    ]
  }
}

Payload out

{"commodity_code": "610910"}

remove_first_characters

Removes a number of characters from the start of a string.

Options

  • (value) — Number of characters to remove.

Example

Payload in

{"name": "#1001"}

Transformation

{
  "order_number": {
    "*ppk*": "name",
    "*post_format*": [
      {"remove_first_characters": 1}
    ]
  }
}

Payload out

{"order_number": "1001"}

remove_last_characters

Removes a number of characters from the end of a string.

Options

  • (value) — Number of characters to remove.

Example

Payload in

{"variant_sku": "TSHIRT-M"}

Transformation

{
  "sku": {
    "*ppk*": "variant_sku",
    "*post_format*": [
      {"remove_last_characters": 2}
    ]
  }
}

Payload out

{"sku": "TSHIRT"}

replace

Finds and replaces text in a string. All occurrences are replaced. Non-strings are returned unchanged.

Options

  • find — Text to look for.

  • replace — Replacement text.

Example

Payload in

{"name": "#UK1001"}

Transformation

{
  "order_number": {
    "*ppk*": "name",
    "*post_format*": [
      {
        "replace": {"find": "#UK", "replace": "ONLINE-"}
      }
    ]
  }
}

Payload out

{"order_number": "ONLINE-1001"}

replace_accent_character

Transliterates accented and non-Latin characters to plain ASCII (ë to e, ß to ss). When applied to an object every value is converted. If a country_code path is given and it resolves to JP, Japanese text is romanised (Hepburn) before transliteration.

Options

  • (value)true, or an object with country_code: a payload path used to detect Japanese addresses.

Example

Payload in

{
  "shipping_address": {"name": "Zoë Müller-Straße"}
}

Transformation

{
  "name": {
    "*ppk*": "shipping_address.name",
    "*post_format*": [
      {"replace_accent_character": true}
    ]
  }
}

Payload out

{"name": "Zoe Muller-Strasse"}

rtrim

Removes the given characters from the end of a string.

Options

  • (value) — Characters to strip.

Example

Payload in

{"desc": "Organic cotton tee.  "}

Transformation

{
  "description": {
    "*ppk*": "desc",
    "*post_format*": [
      {"rtrim": " ."}
    ]
  }
}

Payload out

{"description": "Organic cotton tee"}

serialise_array

Converts a list or object into a JSON string. Strings are returned unchanged. Use when a destination field must hold structured data as text.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "options": {"size": "M", "colour": "Navy"}
}

Transformation

{
  "options_json": {
    "*ppk*": "options",
    "*post_format*": [
      {"serialise_array": true}
    ]
  }
}

Payload out

{"options_json": "{\"size\": \"M\", \"colour\": \"Navy\"}"}

split_and_take

Splits a string on a separator and keeps one part. If the separator is not present, take: 0 returns the whole string and any other index returns an empty string, so a two-line address maps cleanly whether or not the second line exists.

Options

  • on — Separator to split on, for example "\n" or ", ".

  • take — Zero-based index of the part to keep.

Example

Payload in

{"street": "12 High Street\nFlat 3"}

Transformation

{
  "address1": {
    "*ppk*": "street",
    "*post_format*": [
      {
        "split_and_take": {"on": "\n", "take": 0}
      }
    ]
  },
  "address2": {
    "*ppk*": "street",
    "*post_format*": [
      {
        "split_and_take": {"on": "\n", "take": 1}
      }
    ]
  }
}

Payload out

{"address1": "12 High Street", "address2": "Flat 3"}

squash

Joins a list into a single string with a separator. If the list holds objects, add a key after the separator to join the values of that key instead.

Options

  • (value) — The separator, optionally followed by a space and a key: "," or ", sku".

Example

Payload in

{
  "options": ["Navy", "M"],
  "line_items": [
    {"sku": "TSHIRT-M"},
    {"sku": "CAP-01"}
  ]
}

Transformation

{
  "option_values": {
    "*ppk*": "options",
    "*post_format*": [
      {"squash": "/"}
    ]
  },
  "skus": {
    "*ppk*": "line_items",
    "*post_format*": [
      {"squash": ", sku"}
    ]
  }
}

Payload out

{"option_values": "Navy/M", "skus": "TSHIRT-M,CAP-01"}

static_fallback

If the value is empty ("", null or the string "null"), outputs a fixed value instead.

Options

  • (value) — The fallback value, output as a string.

Example

Payload in

{"shipping_title": ""}

Transformation

{
  "ship_by": {
    "*ppk*": "shipping_title",
    "*post_format*": [
      {"static_fallback": "Standard Shipping"}
    ]
  }
}

Payload out

{"ship_by": "Standard Shipping"}

static_value

Replaces the value with a fixed value. Mostly used inside if branches; on its own it is equivalent to the *static_value* field type.

Options

  • (value) — The value to output.

Example

Payload in

{"financial_status": "paid"}

Transformation

{
  "status": {
    "*ppk*": "financial_status",
    "*post_format*": [
      {
        "if": {
          "expression": "==",
          "value": "paid",
          "then": [
            {"static_value": "RELEASED"}
          ],
          "else": [
            {"static_value": "ON_HOLD"}
          ]
        }
      }
    ]
  }
}

Payload out

{"status": "RELEASED"}

store_value

Saves the current value under a key for the rest of the event, and passes it on unchanged. Retrieve it later with the *stored_value* field type or stored_value_fallback. Fields are processed in file order, so store before you read.

Options

  • key — Name to store the value under.

Example

Payload in

{
  "order": {
    "currency": "EUR",
    "line_items": [
      {"sku": "A"},
      {"sku": "B"}
    ]
  }
}

Transformation

{
  "currency": {
    "*ppk*": "order.currency",
    "*post_format*": [
      {
        "store_value": {"key": "currency"}
      }
    ]
  },
  "lines": {
    "*list*": "order.line_items",
    "*list_fields*": {
      "sku": {"*ppk*": "sku"},
      "currency": {"*stored_value*": "currency"}
    }
  }
}

Payload out

{
  "currency": "EUR",
  "lines": [
    {"sku": "A", "currency": "EUR"},
    {"sku": "B", "currency": "EUR"}
  ]
}

stored_value_fallback

If the value is empty, outputs a value saved earlier with store_value.

Options

  • (value) — The key used in store_value.

Example

Payload in

{
  "order": {
    "email": "joe.bloggs@example.com",
    "line_items": [
      {"sku": "A", "recipient_email": ""}
    ]
  }
}

Transformation

{
  "--email": {
    "*ppk*": "order.email",
    "*post_format*": [
      {
        "store_value": {"key": "order_email"}
      }
    ]
  },
  "lines": {
    "*list*": "order.line_items",
    "*list_fields*": {
      "sku": {"*ppk*": "sku"},
      "email": {
        "*ppk*": "recipient_email",
        "*post_format*": [
          {"stored_value_fallback": "order_email"}
        ]
      }
    }
  }
}

Payload out

{
  "lines": [
    {"sku": "A", "email": "joe.bloggs@example.com"}
  ]
}

stream_setting

Replaces the value with a setting from the stream configuration in the Control Panel (destination settings first, then the stream's own settings). Behaves like the *stream_setting* field type but as a post formatting step, which lets it sit inside an if branch.

Options

  • (value) — The setting key.

Example

Payload in

{
  "note_attributes": [
    {"name": "lang", "value": "xx"}
  ]
}

Transformation

{
  "language": {
    "*ppk*": "note_attributes.0.value",
    "*post_format*": [
      {
        "if": {
          "expression": "in",
          "value": ["de", "fr"],
          "then": [
            {"do_nothing": true}
          ],
          "else": [
            {"stream_setting": "default_language"}
          ]
        }
      }
    ]
  }
}

Stream settings

{"default_language": "en"}

Payload out

{"language": "en"}

stream_setting_lookup

Uses the current value as the key of a stream setting and returns that setting. This turns the stream's additional settings into a lookup table that can be edited in the Control Panel without changing the transformation file. When the setting is an object, chain get_value_from_dic to pick a field from it.

Options

  • get_key_from — Must be output: use the current value as the setting key.

  • static_fallback — Optional. Value to output when no setting matches. Without it, no_valid_setting_found is output.

Example

Payload in

{
  "shipping_line": {"code": "EXPRESS"}
}

Transformation

{
  "carrier_service": {
    "*ppk*": "shipping_line.code",
    "*post_format*": [
      {
        "stream_setting_lookup": {"get_key_from": "output", "static_fallback": "STANDARD"}
      }
    ]
  }
}

Stream settings

{"EXPRESS": "DPD-ND", "ECONOMY": "RM-48"}

Payload out

{"carrier_service": "DPD-ND"}

suffix

Adds text to the end of the value.

Options

  • (value) — Text to append.

Example

Payload in

{"name": "1001"}

Transformation

{
  "order_number": {
    "*ppk*": "name",
    "*post_format*": [
      {"suffix": "-PAYPAL"}
    ]
  }
}

Payload out

{"order_number": "1001-PAYPAL"}

sum_list_key

Sums one numeric key across every item of a list and replaces the value with the total. Inside a *list* the list path is relative to the current item; otherwise it is relative to the root of the payload.

Options

  • list — Path to the list.

  • key — Path within each item to sum.

Example

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "total_quantity": {
    "*static_value*": 0,
    "*post_format*": [
      {
        "sum_list_key": {"list": "order.line_items", "key": "quantity"}
      }
    ]
  }
}

Payload out

{"total_quantity": 3.0}

sum_list_key1_by_key2

Multiplies two keys on each item of a list and sums the results, for example quantity times unit price to get an order total. The list path is relative to the root of the payload.

Options

  • list — Path to the list.

  • key_1 — First key to multiply.

  • key_2 — Second key to multiply.

Example

Payload in

{
  "order": {
    "name": "#1001",
    "email": "joe.bloggs@example.com",
    "customer": {"first_name": "Joe", "last_name": "Bloggs"},
    "line_items": [
      {"sku": "TSHIRT-M", "quantity": 2, "price": "19.50"},
      {"sku": "CAP-01", "quantity": 1, "price": "9.50"}
    ]
  }
}

Transformation

{
  "goods_total": {
    "*static_value*": 0,
    "*post_format*": [
      {
        "sum_list_key1_by_key2": {"list": "order.line_items", "key_1": "quantity", "key_2": "price"}
      }
    ]
  }
}

Payload out

{"goods_total": 48.5}

table_lookup

Maps the value through a lookup table. The table can be written inline in the transformation file, or referenced by the UUID of a lookup table maintained in the Control Panel, which lets the mapping be edited without touching the file. Each table key is compared to the value with *match*; if nothing matches, *fallback* is output when given, otherwise the value is unchanged.

Options

  • *match* — Comparison operator, normally ==. Any if expression can be used, for example starts with.

  • *table* — An object of key: value pairs, or the UUID string of a Control Panel lookup table.

  • *fallback* — Optional. Value to output when no key matches.

Inline table with a fallback

Payload in

{"currency": "EUR"}

Transformation

{
  "currency_name": {
    "*ppk*": "currency",
    "*post_format*": [
      {
        "table_lookup": {
          "*match*": "==",
          "*fallback*": "GB Pounds",
          "*table*": {"USD": "US Dollar", "EUR": "Euro", "JPY": "Japanese Yen"}
        }
      }
    ]
  }
}

Payload out

{"currency_name": "Euro"}

Lookup table from the Control Panel

Payload in

{"shipping_code": "EXPRESS"}

Transformation

{
  "carrier_service": {
    "*ppk*": "shipping_code",
    "*post_format*": [
      {
        "table_lookup": {
          "*match*": "==",
          "*fallback*": "STANDARD",
          "*table*": "f670f2c0-4521-11eb-4c83-r98fbd0c4463"
        }
      }
    ]
  }
}

Lookup table

{"EXPRESS": "DPD-ND", "ECONOMY": "RM-48"}

Payload out

{"carrier_service": "DPD-ND"}

title_case

Capitalises the first letter of every word.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "shipping_address": {"country": "united kingdom"}
}

Transformation

{
  "country": {
    "*ppk*": "shipping_address.country",
    "*post_format*": [
      {"title_case": true}
    ]
  }
}

Payload out

{"country": "United Kingdom"}

trim

Removes the given characters from both ends of a string.

Options

  • (value) — Characters to strip, usually " ".

Example

Payload in

{
  "customer": {"first_name": "  Joe "}
}

Transformation

{
  "first_name": {
    "*ppk*": "customer.first_name",
    "*post_format*": [
      {"trim": " "}
    ]
  }
}

Payload out

{"first_name": "Joe"}

uppercase

Converts a string to upper case. Non-strings are returned unchanged.

Options

  • (value) — No options. Pass true.

Example

Payload in

{"postcode": "bs1 4dj"}

Transformation

{
  "postcode": {
    "*ppk*": "postcode",
    "*post_format*": [
      {"uppercase": true}
    ]
  }
}

Payload out

{"postcode": "BS1 4DJ"}

List post formatting

List post formatting functions run on a finished list, after every item has been built. They are listed under *list_post_format* alongside *list* and *list_fields*, and are mostly used to flatten nested data for CSV or XML destinations.

flat_array

Flattens a list of lists into a single list. Use when *list_fields* itself contains a *list*, which produces one inner list per outer item.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "orders": [
    {
      "name": "#1001",
      "line_items": [
        {"sku": "A"},
        {"sku": "B"}
      ]
    },
    {
      "name": "#1002",
      "line_items": [
        {"sku": "C"}
      ]
    }
  ]
}

Transformation

{
  "lines": {
    "*list*": "orders",
    "*list_fields*": {
      "*list*": "line_items",
      "*list_fields*": {
        "sku": {"*ppk*": "sku"},
        "order": {"*ppk*": ".orders.0.name"}
      }
    },
    "*list_post_format*": [
      {"flat_array": true}
    ]
  }
}

Payload out

{
  "lines": [
    {"sku": "A", "order": "#1001"},
    {"sku": "B", "order": "#1001"},
    {"sku": "C", "order": "#1001"}
  ]
}

Note that inside the inner list .orders.0.name reads from the root of the payload, so it always returns the first order's name. To carry the parent's fields into each child row, reshape the payload first with the merge_up pre-formatter.

merge_down

Moves the items of a nested list up to sit alongside their parent. For each item in the list, the named key is removed and its items are appended directly after the parent item. Useful for bill-of-materials or kit structures where the destination expects components as extra rows.

Options

  • (value) — The key on each item that holds the nested list.

Example

Payload in

{
  "lines": [
    {
      "sku": "KIT-01",
      "qty": 1,
      "components": [
        {"sku": "PART-A", "qty": 2},
        {"sku": "PART-B", "qty": 1}
      ]
    },
    {
      "sku": "CAP-01",
      "qty": 1,
      "components": []
    }
  ]
}

Transformation

{
  "rows": {
    "*list*": "lines",
    "*list_fields*": {
      "sku": {"*ppk*": "sku"},
      "qty": {"*ppk*": "qty"},
      "components": {
        "*list*": "components",
        "*list_fields*": {
          "sku": {"*ppk*": "sku"},
          "qty": {"*ppk*": "qty"}
        }
      }
    },
    "*list_post_format*": [
      {"merge_down": "components"}
    ]
  }
}

Payload out

{
  "rows": [
    {"sku": "KIT-01", "qty": 1},
    {"sku": "PART-A", "qty": 2},
    {"sku": "PART-B", "qty": 1},
    {"sku": "CAP-01", "qty": 1}
  ]
}

remove_empty_values

Removes null and empty-string items from a list. Typically used after *list_field* when some items have no value.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "fulfillments": [
    {"tracking": "JD0001"},
    {"tracking": ""},
    {"tracking": "JD0003"}
  ]
}

Transformation

{
  "tracking_numbers": {
    "*list*": "fulfillments",
    "*list_field*": {"*ppk*": "tracking"},
    "*list_post_format*": [
      {"remove_empty_values": true}
    ]
  }
}

Payload out

{
  "tracking_numbers": ["JD0001", "JD0003"]
}

serialise_array

Converts the finished list into a JSON string. The same function is available as a post formatting function for single values.

Options

  • (value) — No options. Pass true.

Example

Payload in

{
  "tags": [
    {"name": "vip"},
    {"name": "wholesale"}
  ]
}

Transformation

{
  "tags_json": {
    "*list*": "tags",
    "*list_field*": {"*ppk*": "name"},
    "*list_post_format*": [
      {"serialise_array": true}
    ]
  }
}

Payload out

{"tags_json": "[\"vip\", \"wholesale\"]"}