Introduction

The JS7 - JITL REST API Jobs offer use of jq, https://jqlang.org to process the JSON response of requests to REST APIs.

  • The query language is provided by jackson-jq, https://github.com/eiiches/jackson-jq, the Java implementation of jq.
  • Users can check the jq manual for relevant explanations how to extract and to process data from JSON responses.
  • A few differences between jq and jackson-jq should be considered that are explained from the jackson-jq web site.

JITL REST API Jobs make use of jq 1.7 offered by jackson-jq.

The jq query language can be used with the return_variable argument of JITL REST API Jobs.

Users find more examples how to use jq with their jobs from the JS7 - JITL JS7RESTClientJob.

FEATURE AVAILABILITY STARTING FROM RELEASE 2.8.0

Query Language for Return Values

Let's start from a few practical examples.

Examples

Example for REST Request to /orders/add Endpoint

Find an example for a REST request to the JS7 - REST Web Service API that is made available with the request argument of the JS7 - JITL JS7RESTClientJob.

  • Lines 2 to 4 hold general settings for execution with JITL REST API Jobs
  • Lines 5 to 52 hold the body of the REST request as suggested by the /orders/add endpoint.
    • Users can specify variables from a number of sources: any variables assigned the workflow and job arguments, variables from JS7 - Job Resources and built-in variables can be used, see JS7 - Expressions for Variables. Such variables will be substituted at run-time by the job. The syntax for referencing variables is: ${variable}
    • The js7ControllerId and js7WorkflowPath variables are available at global level for any jobs, for a full list see JS7 - Expressions for Variables.
    • The workflow variable workflow specified in the request is assumed to be declared by the underlying workflow.

Example for REST Request to /orders/add Endpoint
{
  "endpoint": "/orders/add",
  "method": "POST",
  "headers": [],
  "body": {
    "controllerId": "${js7ControllerId}",
    "orders": [
      {
        "workflowPath": "${workflow}",
        "orderName": "AddOrders-1",
        "forceJobAdmission": false,
        "tags": [],
        "arguments": {},
        "scheduledFor": "now"
      },
      {
        "workflowPath": "${workflow}",
        "orderName": "AddOrders-2",
        "forceJobAdmission": false,
        "tags": [],
        "arguments": {},
        "scheduledFor": "now"
      },
      {
        "workflowPath": "${workflow}",
        "orderName": "AddOrders-3",
        "forceJobAdmission": false,
        "tags": [],
        "arguments": {},
        "scheduledFor": "now"
      },
      {
        "workflowPath": "${workflow}",
        "orderName": "AddOrders-4",
        "forceJobAdmission": false,
        "tags": [],
        "arguments": {},
        "scheduledFor": "now"
      },
      {
        "workflowPath": "${workflow}",
        "orderName": "AddOrders-5",
        "forceJobAdmission": false,
        "tags": [],
        "arguments": {},
        "scheduledFor": "now"
      }
    ],
    "auditLog": {
        "comment": "5 orders added to workflow [${workflow}] by workflow: ${js7WorkflowPath}"
    }
  }
}

Example for JSON Response of /orders/add Endpoint

The follwoing JSON response is an example returned from a request to the /orders/add endpoint that adds a few orders:

  • The response holds two top-level elements deliveryDate and orderIds.
  • The orderIds element includes an array of 5 Order IDs created.

Example for JSON Response
{
  "deliveryDate": "2025-06-20T14:24:34.403+00:00",
  "orderIds": [
    "#2025-06-20#T42947440212",
    "#2025-06-20#T42947440111",
    "#2025-06-20#T42947439709",
    "#2025-06-20#T42947440110",
    "#2025-06-20#T42947440213"
  ]
}


From the above example users can access elements of the JSON response and can extract related values using jq queries like this

PurposeQueryReturn Value
Return the delivery date.deliveryDate"2025-06-20T14:24:34.403+00:00"
Return an individual Order ID, for example the first one.orderIds[0]"#2025-06-20#T42947440212"
Return the comma separated list of Order IDs.orderIds[]"#2025-06-20#T42947440212",
"#2025-06-20#T42947440111",
"#2025-06-20#T42947439709",
"#2025-06-20#T42947440110",
"#2025-06-20#T42947440213"
Return an array of Order IDs[.orderIds]

[
  "#2025-06-20#T42947440212",
  "#2025-06-20#T42947440111",
  "#2025-06-20#T42947439709",
  "#2025-06-20#T42947440110",
  "#2025-06-20#T42947440213"
]

Return the number of orders created.orderIds | length

5

Example for JSON Response of /orders Endpoint

The follwoing JSON response is an example returned from a request to the /orders endpoint that provides details for 2 orders available in JS7:

Example for JSON Response
{
    "deliveryDate": "2025-06-20T14:49:45.107+00:00",
    "surveyDate": "2025-06-20T14:24:34.519+00:00",
    "orders": [
        {
            "orderId": "#2025-06-23#P13497079036",
            "workflowId": {
                "path": "/example/hello",
                "versionId": "b50a8047-88fd-4fa1-a6e5-385030add6a9"
            },
            "state": {
                "severity": 1,
                "_text": "SCHEDULED"
            },
            "attachedState": {
                "TYPE": "Attaching"
            },
            "planId": {
                "noticeSpaceKey": "2025-06-23",
                "planSchemaId": "DailyPlan"
            },
            "label": "add-orders",
            "position": [ 0, "try", 0 ],
            "positionString": "0/try:0",
            "scheduledFor": 1750629600000,
            "scheduledNever": false,
            "hasChildOrders": false,
            "isContinuable": true,
            "isSuspendible": true,
            "priority": 0
        },
        {
            "orderId": "#2025-06-23#P13497079036",
            "workflowId": {
                "path": "/example/hello",
                "versionId": "b50a8047-88fd-4fa1-a6e5-385030add6a9"
            },
            "state": {
                "severity": 1,
                "_text": "RUNNING"
            },
            "attachedState": {
                "TYPE": "Attaching"
            },
            "planId": {
                "noticeSpaceKey": "2025-06-23",
                "planSchemaId": "DailyPlan"
            },
            "label": "add-orders",
            "position": [ 0, "try", 0 ],
            "positionString": "0/try:0",
            "scheduledFor": 1750629600000,
            "scheduledNever": false,
            "hasChildOrders": false,
            "isContinuable": true,
            "isSuspendible": true,
            "priority": 0
        }
    ]
}


From the above example users can access elements of the JSON response and can extract related values using jq queries like this:

PurposeQuery ExampleReturn Value
Return Order IDs and workflow path per order.orders[] | .orderId, .workflowId.path#2025-06-23#P13497079036
/example/hello
#2025-06-23#P13497079036
/example/hello
Return Order IDs for orders in RUNNING state.orders[] | select(.state._text == \"RUNNING\") | .orderId#2025-06-23#P13497079036
Return the number of orders in RUNNING state[.orders[] | select(.state._text == \"RUNNING\") | .orderId] | lengthnumber of elements
Return the number of orders in SCHEDULED or RUNNING state[.orders[] | select([.state._text] | inside([\"SCHEDULED\",\"RUNNING\"])) | .orderId] | length

number of elements

Using Return Variables

From above examples the return_variable job argument specifies a JSON document that holds the name and path of Return Variables.

  • name: holds the name of the Return Variable.
  • path: holds the query to extract data from the JSON response to a REST request.

Example for return_variable Job Argument
[
  {
    "name": "order_ids",
    "path": ".orderIds"
  },
  {
    "name": "order_id",
    "path": ".orderIds[0]"
  }
]


The JS7RESTClientJob and RESTClientJob will create dynamic workflow variables from the indicated Return Variables.

In order to use Return Variables in a subsequent Shell job, they can be mapped to environment variables of the Shell job like this:

  • In the Configuration view for the workflow, users can select the job and can specify mappings.
  • Users are free to choose the names of environment variables and assign the related Return Variables: $order_ids and $order_id


When the job is executed, its log output will look like this:

Example for Log Output of Job
2025-06-20 20:19:41.731+02:00 [MAIN] [OrderProcessingStarted] id=#2025-06-20#T45077780600-ap, Job=display-results, label=display-results, pos=1, Agent(url=https://agent-2-0-primary:4443, name=primaryAgent, time=2025-06-20 20:19:41.666+02:00)
2025-06-20 20:19:41.666+02:00 [MAIN]    [Start] Job=display-results, label=display-results, Agent(url=https://agent-2-0-primary:4443, id=primaryAgent, name=primaryAgent)
2025-06-20 20:19:41.753+02:00 [STDOUT]  
Order IDS: ["#2025-06-20#T45078134501-root"]
Order ID: "#2025-06-20#T45078134501-root"
2025-06-20 20:19:41.753+02:00 [MAIN]    [End] [Success] returnCode=0


When specifying Return Variables then users can add comments by introducing JSON elements that will not be considered by JITL REST Jobs:

  • Users can add comments from a _comment element.
  • Prefixing name and path elements with an underscore disables processing of the Return Variable.

Example for return_variable Job Argument
[
  {
    "_comment": "earlier version of the query",
    "_name": "order_ids",
    "_path": "[.orderIds]"
  },
  {
    "_comment": "current version of the query",
    "name": "order_ids",
    "path": ".orderIds"
  },
 ]

Processing Instructions

The JITL REST API job templates offer options to control and to extend the behavior of jq.

A processing instruction is prepended or appended to a jq query expression.

Input Processing Instruction

A number of options to manage input to jq are available from the Input Processing Instruction.

FEATURE AVAILABILITY STARTING FROM RELEASE 2.8.1

Syntax

<  [plain: | json:]  [<option> [<option>]]  ||  <jq-query>

Examples

InputQualifier                    Options          SeparatorExample
<[plain: | json:][<option> [<option>]]||




populate Return Variable from plain text response:

< plain:





process JSON response (default):

< json:



-q | --request-header

< --request-header || .js7RequestHeader.accept

< --request-header=accept || .js7RequestHeader.accept



-d | --request-body
< --request-body || .controllerId, .auditLog.comment


-s | --response-header

< --response-header || .js7ResponseHeader.\"content-type\" 

< --response-header=content-type || .js7ResponseHeader.\"content-type\" 



-b | --response-body

.< --response-body || .deliveryDate

.deliveryDate 



--from-json

< json: --from-json={\"myString\":\"some string\"} || .myString

< json: --from-json={\"myNumber\":42} || .myNumber

< json: --from-json='{\"myArray\": [{\"name\": \"my-name\"},{\"value\": \"myValue\"}]}' || map(.[]) | join(\" \")


Explanations:

  • The Input Processing Instruction is prepended a jq query expression.
  •  Input
    • The < character identifies the Input Processing Instruction.
  • Qualifier
    • The plain: qualifier specifies input from plain text, for example if a response body holds plain text such as log output.
    • The json: qualifier specifies input in JSON format (default).
  • Options
    • Options are not exclusive, more than one of the below options can be specified, separated by spaces.
    • -q | --request-header
      • Allows access to the response body and to request headers which are available to jq from the .js7RequestHeader object followed by the header name in lowercase spelling.
      • When specified without a header name, then all request headers will be made available to jq.
      • When specified with a header name, then the related request header will be made available to jq.
      • Mixed spelling of header names is allowed for the value of the option. Lowercase spelling of header names is required in jq query expressions.
    • -d | --request-body
      • Specifies that the response body is made available to jq from the .js7RequestBody object.
    • -s | --response-header
      • Offers to access to the response body response headers which are available to jq from the .js7ResponseHeader object followed by the header name in lowercase spelling.
      • When specified without a header name, then the all response headers will be made available to jq.
      • When specified with a header name, then the related response header will be made available to jq.
      • Mixed spelling of header names is allowed for the value of the option. Lowercase spelling of header names is required in jq query expressions.
    • -b | --response-body
      • Specifies that the response body is used for input to jq. Elements of the response body can be directly accessed in jq expressions.
      • The option is the default Input Processing Instruction: when no Input Processing Instruction is specified, then the response body is used as input for jq.
    • --from-json
      • Specifies direct input in JSON format to jq.
      • The option requires specifying a valid JSON document.
      • To specify a JSON with spaces, enclose it in single quotes. Example:  --from-json='{\"myNumber\" : 42}'.
  • Separator
    • The || characters separate the Input Processing Instruction from the jq query expression.

Output Processing Instruction

A number of options to manage output are available from use of an Output Processing Instruction.

Syntax

<jq-query>  ||  [<option> [<option>]]  [> | >>  path] 

Examples

SeparatorOptionsRedirectionExampleOutput
||[<option> [<option>]][> | >>  path].orders[] | .orderId

Without Output Processing Instruction returns quoted output:

"#2025-06-23#P13497079036"
"#2025-06-23#P13497078265"


-r | --raw-output
.orders[] | .orderId || --raw-output

Returns raw, unquoted output:

#2025-06-23#P13497079036
#2025-06-23#P13497078265



> path.orders[] | .orderId, .workflowId.path || > /tmp/orders.txtCreates a new file or overwrites an existing file.



. || > /tmp/orders.jsonCopies the JSON response body to a file.



[.orders[] | {myOrderId: .orderId, myWorkflow: .workflowId.path}] || > /tmp/orders.json

Creates a new file that holds an array of elements:

[
  {
 
   "myOrderId": "#2025-06-23#P13497079036",
    "myWorkflow": "/example/hello"
  },
  {
    "myOrderId": "#2025-06-23#P13497079036",
    "myWorkflow": "/example/hello"
  }
]



>> path.orders[] | .orderId, .workflowId.path || >> /tmp/orders.txtCreates a new file or appends to an existing file.


Explanations:

  • The Output Processing Instruction is appended to a jq query expression.
  • Separator
    • The || characters separate the jq query expression from the Output Processing Instruction.
  • Options
    • -r | --raw-output
      • Raw output strips quotes from string values.
  • Redirection
    • >  |  >>
      • > specifies that output will be written to a new file or will overwrite an existing file.
      • >> specifeis that output will be written to a new file or will be appended to an existing file.
    • path
      • Specifies the path to the output file. Relative paths start from the Agents' working directory that is specified during installation and that defaults to the <agent-data> directory.
    • When output is redirected to a file, then the Return Variable will not hold the output of the query but will hold the path to the file that was used.

Logging

Responses from the JS7 REST API can grow large. For example, if a query of the order history or task history is performed then size of output can exceed several MB.

To this purpose the REST responses will not be added to log ouput at info level.

Users who wish to analyze responses

  • can write the response to a file, see above Processing Instructions,
  • can run the job with debug log level to find the response body in the log output.


Log LevelRequestResponse
infoyesno
debugyesyes


Find details how to specify log levels from the JS7 - JITL Common Parameterization article.

Resources


  • No labels