# JSONtransforms

{% hint style="warning" %}
This feature is only enabled on certain environments and tenants. Please contact [Support](/support/support.md) for more information about this feature.
{% endhint %}

With the [Transforms API](/spark-apis/transforms-api.md) we are able to support many types of transform definitions. This document describes the transform type `JSONtransforms`.

In this transform we are able to convert JSON content to requests and responses that are compatible with the Spark [Execute API](/spark-apis/execute-api.md). [JSONata](https://jsonata.org) is a "lightweight query and transformation language for JSON data". You can test your [JSONata](https://jsonata.org) transforms in the [JSONata Exerciser](https://try.jsonata.org/).

We recommend this transform type if you have a complex JSON transformation that you would like to perform on a single request and response.

<figure><img src="/files/5zrp8IdftJ1BmIoNpJE1" alt=""><figcaption></figcaption></figure>

## Transform document

[Transform documents](/spark-apis/transforms-api/transform-documents.md) are used to define the code relating to a transform. For `JSONtransforms`, the transform document is a JSON document defined by the following objects:

| Key                     | Value                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `transform_type`        | Note the [JSONata](https://jsonata.org) package versions used in [Update roadmap](/spark-apis/transforms-api/transform-types/update-roadmap.md).                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| s`target_api_version`   | <p>Optional parameter.<br>This can be either <code>v3</code> or <code>v4</code> depending on  whether to target the <a data-mention href="/pages/nsJig8FRhYDL3hcSAwbt">/pages/nsJig8FRhYDL3hcSAwbt</a> or <a data-mention href="/pages/F63N1Fpz7fYruDnmWkEQ">/pages/F63N1Fpz7fYruDnmWkEQ</a>.<br>If omitted, then the default is <code>v3</code>.</p>                                                                                                                                                                                                                                                  |
| `input_body_transform`  | <p>Optional parameter.<br>Single string containing the code for the input transform. Any double quotation marks <code>"</code> need to be escaped, i.e. <code>"</code> is replaced with <code>"</code>. This will be processed against the request body to the <code>/transforms</code> endpoint.<br>If omitted, no transformation will take place.<br>The result will automatically be put under the <a data-mention href="/pages/i1Gw4hnm5WLCg1qp8zNM">/pages/i1Gw4hnm5WLCg1qp8zNM</a> <code>inputs</code> object.<br><br>See the <a data-mention href="#example">#example</a> for more details.</p> |
| `output_body_transform` | <p>Optional parameter.<br>Single string containing the code for the output transform. Any double quotation marks <code>"</code> need to be escaped, i.e. <code>"</code> is replaced with <code>"</code>.<br>If omitted, no transformation will take place.<br>This will be processed against the response body of the <a data-mention href="/pages/i1Gw4hnm5WLCg1qp8zNM">/pages/i1Gw4hnm5WLCg1qp8zNM</a>.<br><br>See the <a data-mention href="#example">#example</a> for more details.</p>                                                                                                            |

```json
{
  "transform_type": "JSONtransforms_v1.0.1",
  "target_api_version": "v3",
  "input_body_transform":"{\"add_1\":add.a,\"add_2\":add.b,\"multiply_1\":multiply.a,\"multiply_2\":multiply.b}",
  "output_body_transform":"{\"add\":{\"result\":response_data.outputs.add},\"multiply\":{\"result\":response_data.outputs.multiply},\"meta\":{\"id\":response_meta.call_id}}"
}
```

## Build transforms

To build transforms you can follow the instructions for the specific transform on this page. For JavaScript developers there is also the [Node Transform Document Builder](https://github.com/floherent/node-transform-builder) that can be used to assist with the development.

## Transforms API

These details are specific to this transform in addition to information in [Transforms API](/spark-apis/transforms-api.md).

### Request headers

In addition to the [Transforms API](/spark-apis/transforms-api.md) [#request-headers](#request-headers "mention"), these are specific to this transform.

Meta parameters are included in the request headers to keep the request body as generic as possible to conform to the calling system format.

<table data-full-width="false"><thead><tr><th>Key</th><th>Value</th></tr></thead><tbody><tr><td><code>Content-Type</code></td><td><code>application/json</code></td></tr><tr><td><code>x-meta</code></td><td>Optional parameter.<br>If using <code>target_api_version</code> <code>v4</code>, this should contain a single string containing a JSON object with key value pairs of the  <a data-mention href="/pages/F63N1Fpz7fYruDnmWkEQ">/pages/F63N1Fpz7fYruDnmWkEQ</a> <a data-mention href="/pages/F63N1Fpz7fYruDnmWkEQ#request-body">/pages/F63N1Fpz7fYruDnmWkEQ#request-body</a> parameters. Any double quotation marks <code>"</code> need to be escaped, i.e. <code>"</code> is replaced with <code>\"</code>.<br>Example:  <br><code>"{\"version_id\":\"86da8bea-b900-4bf2-8bcf-6a365ac91a4d\"}"</code></td></tr><tr><td><code>x-request-meta</code></td><td>Optional parameter.<br>If using <code>target_api_version</code> <code>v3</code>, this should contain a single string containing a JSON object with key value pairs of the <a data-mention href="/pages/nsJig8FRhYDL3hcSAwbt">/pages/nsJig8FRhYDL3hcSAwbt</a> <a data-mention href="/pages/nsJig8FRhYDL3hcSAwbt#request_meta">/pages/nsJig8FRhYDL3hcSAwbt#request_meta</a> parameters. Any double quotation marks <code>"</code> need to be escaped, i.e. <code>"</code> is replaced with <code>\"</code>.<br>Example:  <br><code>"{\"call_purpose\":\"Transform mainframe request\"}"</code></td></tr></tbody></table>

### Request body

* Content must be in JSON.

### Limitations

* The API call has a maximum lifetime of `270 s`.

### Response headers

<table data-full-width="false"><thead><tr><th>Key</th><th>Value</th></tr></thead><tbody><tr><td><code>Content-Type</code></td><td><code>application/json</code></td></tr><tr><td><code>x-meta</code></td><td>Optional parameter.<br>If using <code>target_api_version</code> <code>v4</code>, this should contain a single string containing a JSON object with key value pairs of the  <a data-mention href="/pages/F63N1Fpz7fYruDnmWkEQ">/pages/F63N1Fpz7fYruDnmWkEQ</a> <a data-mention href="/pages/F63N1Fpz7fYruDnmWkEQ#request-body">/pages/F63N1Fpz7fYruDnmWkEQ#request-body</a> parameters. Any double quotation marks <code>"</code> need to be escaped, i.e. <code>"</code> is replaced with <code>\"</code>.<br>Example: <br><code>"{\"version_id\":\"86da8bea-b900-4bf2-8bcf-6a365ac91a4d\"}"</code></td></tr><tr><td><code>x-request-meta</code></td><td>Optional parameter.<br>If using <code>target_api_version</code> <code>v3</code>, this should contain a single string containing a JSON object with key value pairs of the <a data-mention href="/pages/nsJig8FRhYDL3hcSAwbt">/pages/nsJig8FRhYDL3hcSAwbt</a> <a data-mention href="/pages/nsJig8FRhYDL3hcSAwbt#request_meta">/pages/nsJig8FRhYDL3hcSAwbt#request_meta</a> parameters. Any double quotation marks <code>"</code> need to be escaped, i.e. <code>"</code> is replaced with <code>\"</code>.<br>Example: <br><code>"{\"call_purpose\":\"Transform mainframe request\"}"</code></td></tr></tbody></table>

### Response body

* Content will be in JSON.
* If the Spark [Execute API](/spark-apis/execute-api.md) encounters an error, the error from the [Execute API](/spark-apis/execute-api.md) will be returned.

### HTTP status code

By default the status code for a successful transformation will be `200`. You can also ask the transform to return a custom status code that can be consumed by your application.

If the transformation was successful and the completed output transform includes the key `spark_transform_response_httpstatuscode` then Spark will use the value of this key as the returned status code.

For example:

<table data-header-hidden><thead><tr><th width="549"></th><th></th></tr></thead><tbody><tr><td><pre class="language-json" data-overflow="wrap"><code class="lang-json">{
  ...
  "spark_transform_response_httpstatuscode": 422
  ...
}
</code></pre></td><td>This would result in the HTTP status code returned as <code>422 Unprocessable Entity</code></td></tr></tbody></table>

## Example

In this example the calling system would like to perform addition and multiplication operations but it is in a different format to the Spark service. The Spark service has its inputs and outputs defined as:

* For this example we will be using the [Execute API (v3)](/spark-apis/execute-api/execute-api-v3.md).
* `Xoutput_add` = `Xinput_add_1+Xinput_add_2`
* `Xoutput_multiply` = `Xinput_multiply_1*Xinput_multiply_2`
* For the Spark [Execute API (v3)](/spark-apis/execute-api/execute-api-v3.md) call, we also want to note the `call_purpose`.
* In the response, we would like to include the [Execute API (v3)](/spark-apis/execute-api/execute-api-v3.md) [Execute API (v3)](/spark-apis/execute-api/execute-api-v3.md#response_meta) `call_id`.

{% file src="/files/3cLTZIZEwSI6W48k2YcY" %}

The below illustrates how the request is transformed to match the Spark [Execute API (v3)](/spark-apis/execute-api/execute-api-v3.md) format and how the response is transformed to match the required system response.

<table><thead><tr><th>Request</th><th>JSONata transform</th><th>Transformed request</th></tr></thead><tbody><tr><td><pre class="language-json"><code class="lang-json">{ 
 "add": {
   "a":3,
   "b":4
  },
  "multiply": {
    "a":5,
    "b":6
  }
}
</code></pre></td><td><pre><code>{
 "add_1": add.a,
 "add_2": add.b,
 "multiply_1": multiply.a,
 "multiply_2": multiply.b
}
</code></pre></td><td><pre class="language-json"><code class="lang-json">{
  "add_1": 3,
  "add_2": 4,
  "multiply_1": 5,
  "multiply_2": 6
}
</code></pre></td></tr></tbody></table>

<table><thead><tr><th>Spark response</th><th>JSONata transform</th><th>Transformed response</th></tr></thead><tbody><tr><td><pre class="language-json"><code class="lang-json">{
  "response_data": {
    "outputs": {
      "add": 7,
      "multiply": 30
    },
    "warnings": null,
    "errors": null,
    "service_chain": null
  },
  "response_meta": {
    "service_id": "0a95218a-5c7a-468a-b82d-3f7c41097eae",
    "version_id": "6c80f4a8-a559-488d-8a30-c66824655eac",
    "version": "0.1.0",
    "process_time": 5,
    "call_id": "3790cd02-b423-47f3-96f4-262bbf6c306e",
    "compiler_type": "Neuron",
    "compiler_version": "1.18.0",
    "source_hash": null,
    "engine_id": "0B9C0B1B71CB230CD78E23886AA574AA",
    "correlation_id": "",
    "parameterset_version_id": null,
    "system": "SPARK",
    "request_timestamp": "2024-04-29T01:41:56.737Z"
  }
}
</code></pre></td><td><pre><code>{
 "add":{
  "result": response_data.outputs.add
  },
 "multiply":{
  "result": response_data.outputs.multiply
 },
 "meta":{
  "id": response_meta.call_id
 }
}
</code></pre></td><td><pre class="language-json"><code class="lang-json">{
  "add": {
    "result": 7
  },
  "multiply": {
    "result": 30
  },
  "meta": {
    "id": "3790cd02-b423-47f3-96f4-262bbf6c306e"
  }
}
</code></pre></td></tr></tbody></table>

### Create the transform document

The transform can be assembled into the transform document as attached below.

1. Follow the instructions in [Transform documents](/spark-apis/transforms-api/transform-documents.md#create-new-transform-documents) to create a new transform in the folder of your choice.
2. The *Transform type* is `JSONata_v1.0.1`.
3. Since we are using [Execute API (v3)](/spark-apis/execute-api/execute-api-v3.md), choose *Target API version* as `v3`.
4. Copy and paste the JSONata transforms above in to the *Request transform* and *Response transform* respectively.

Alternatively the document can be manually created and uploaded to Spark using the *New transforms* featur&#x65;*.*

1. The `transform_type` is `JSONata_v1.0.1`.
2. Since we are using [Execute API (v3)](/spark-apis/execute-api/execute-api-v3.md), the `target_api_version` is `v3`.
3. Both the `input_body_transform` and `output_body_transform` each must be a single string containing the code for the transform.
   1. Remove any lines containing comments.
   2. Any double quotation marks `"` need to be escaped, i.e. `"` is replaced with `\"`.
      * Note that [JSONata](https://jsonata.org) allows for single quotation marks `'` to be interchanged with double quotation marks `"`. If `'` are used exclusively in lieu or `"`, then the escape character is not needed.
   3. If you are using [Visual Studio Code](https://code.visualstudio.com/), you can use the *Join lines* feature to make it easy to combine multiple lines into a single string.
      1. Select the transform text that you would like to combine onto a single line.
         1. Access the *Command Palette* `F1` or `Ctrl+Shift+P` on Windows or `Shift+⌘+P` on Mac.
         2. Type in the command *Join lines* and select it.
   4. As an alternative to *Join lines*, line breaks `Ctrl+Enter` can be replaced with the new line character `\n`.
4. Follow the instructions on [Transform documents](/spark-apis/transforms-api/transform-documents.md) to upload the transform document to Spark.

{% file src="/files/IBtxFhMfLPbmP63uykse" %}

### Sample request

```sh
curl --location 'https://excel.myenvironment.coherent.global/mytenant/api/v4/transforms/mytransformsfolder/mytransformsname/for/myservicefolder/myservicename' \
--header 'Accept-Encoding: gzip' \
--header 'Content-Type: application/json' \
--header 'x-request-meta: "{\"call_purpose\":\"Documentation example - arithmetic\"}"' \
--header 'Authorization: Bearer {token}' \
--data '{
    "add": {
        "a": 3,
        "b": 4
        
    },
    "multiply": {
        "a": 5,
        "b": 6
    }
}'
```

### Sample response

```json
{
  "add": {
    "result": 7
  },
  "multiply": {
    "result": 30
  },
  "meta": {
    "id": "d15446c7-20be-4e5c-9062-0c723b2f3eda"
  }
}
```

## Sample JSONata

### Convert JSON "records" table to array table

{% tabs %}
{% tab title="Sample request" %}

```json
{
  "table": [
    { "a": 2, "b": 1                 },
    {         "b": 3, "c": 4         },
    {                 "c": 5, "d": 6 }
  ]
}
```

{% endtab %}

{% tab title="JSONata" %}

```
(
    /* convert JSON record table to array table */
    $table_to_array := function($input_table) {(
        $table_keys := $keys($input_table);
        /* create key value pair of all keys with a value of null */
        $key_null := [$reduce($table_keys, function($acc, $v) { $merge([$acc, {$v: null}]) }, {})];

        /* for each row merge key_null with the table record */
        /* keys without values will be null */
        /* convert the result to a csv of values */
        $csv_row := function($input_row) {(
            $merged_null := $merge([$key_null, $input_row]);
            $csv := [$each($merged_null, function($v, $k) {$v})];
            $csv
        )};

        [[$table_keys], $map($input_table, $csv_row)];
    )};

    {
        "csv_table": $table_to_array(table)
    };
)
```

{% endtab %}

{% tab title="Sample response" %}

```json
{
  "csv_table": [
    [ "a" , "b" , "c",  "d"  ],
    [    2,    1, null, null ],
    [ null,    3,    4, null ],
    [ null, null,    5,    6 ]
  ]
}
```

{% endtab %}
{% endtabs %}

### Convert items with index suffices into an array of objects

Select items with the index suffices `_#` identified in `number_of_plans`.

{% tabs %}
{% tab title="Sample request" %}

```json
{
  "response_data": {
    "outputs": {
      "number_of_plans": "2,3",
      "AnnualPremium_1": 46.1,
      "AnnualPremium_2": 46.2,
      "AnnualPremium_3": 46.3,
      "AnnualPremium_4": 46.4,
      "PaymentFreq_1": 1,
      "PaymentFreq_2": 2,
      "PaymentFreq_3": 3,
      "PaymentFreq_4": 4
    }
  }
}
```

{% endtab %}

{% tab title="JSONata" %}

```
(
    $data := $.response_data.outputs;
    $plan_output := function($index) {(
       {
           "PlanNumber": $index,
           "AnnualPremium": $lookup($data, "AnnualPremium_"&$index),
           "Payment": {
               "Freq": $lookup($data, "PaymentFreq_"&$index)
           }
       };
    )};
    
    $result := None;
    $contains($data.number_of_plans, '1') ? $result := $append($result, $plan_output(1)) : $result;
    $contains($data.number_of_plans, '2') ? $result := $append($result, $plan_output(2)) : $result;
    $contains($data.number_of_plans, '3') ? $result := $append($result, $plan_output(3)) : $result;
    $contains($data.number_of_plans, '4') ? $result := $append($result, $plan_output(4)) : $result;    
)
```

{% endtab %}

{% tab title="Sample response" %}

```json
[
  {
    "PlanNumber": 2,
    "AnnualPremium": 46.2,
    "Payment": { "Freq": 2 }
  },
  {
    "PlanNumber": 3,
    "AnnualPremium": 46.3,
    "Payment": { "Freq": 3 }
  }
]
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.coherent.global/spark-apis/transforms-api/transform-types/jsontransforms.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
