Introduction

The XML or JSON Query Service is used for making requests to remote APIs, similar to the Remote Query Block (RQB). However, while the RQB can only send request data using query parameters (in the URL) and/or url-encoded form data (in the request body), the XML or JSON Query Service can send any kind of text-based body, such as XML or JSON. (You could even send url-encoded form data using the XML or JSON Query Service since that's also a text format, but in most cases the RQB will be much easier to use for such a request.)

The XML or JSON Query Service also has more limited capabilities for parsing API responses than the RQB. The most common usage of the XML or JSON Query Service is to use a javascript to parse individual values from the response and set them as EachScape variables.

Configuring the Request

To make a request to a remote API using the XML or JSON Query Service, first enter the URL of the remote API in the URL field and choose the HTTP method required by the API. Most APIs that accept JSON or XML requests will use the POST method, but you should consult the documentation of your API to see what it expects.

Header fields provide additional information to the server about how to handle your request. Some examples of the kind of information you might send as a header include authentication data, information about what kind of data you are sending the server and information about what kind of data you want the server to return. 

For most APIs, you should set a Content-Type header and an Accept header, which tell the server what format you’re sending data in, and what format or formats the server can send back, respectively. The value of Content-Type should be the MIME type of the format you are using to send your request. For a JSON request, your Content-Type header should have a value of “application/json”; for an XML request, your Content-Type header should have a value of “application/xml”. 

If you know that the remote server will only return one format, you can usually set the Accept header’s value to “*/*”, meaning you are happy with any response format. However, if the API can return several possible formats, make sure you tell it which format you want back. As with Content-Type, if you want server to return a JSON response, your Accept header should have a value of “application/json”, and if you want the server to return an XML response your Accept header should have a value of “application/xml”.

The screenshot below shows the configuration of an API request that sends a POST to https://api.example.com/data.json telling the server that the request is in the JSON format and asking the server to return its response in the JSON format.

The Body field should contain the XML or JSON (or other text format) data that you want to send to the server. Make sure that the format of the body matches the value of the Content-Type header!

Parsing the Response

The Status Code Variable and Status Description Variable fields enable you to define variables that will help you determine if the request was successful. These variables are set by the XML or JSON Query Service before calling the Success, Failure and Complete events. The Status Code Variable will be set to the HTTP status code of the response (e.g., 200 for a successful call) and the Status Description Variable will be set to the test description of the HTTP status (e.g., “Success” for a 200 response code). You can do some basic error handling in your Failure event by checking these status codes; for example, an 401 response code might indicate that you need to re-authenticate before you can make your request successfully.

For more complex cases where you need data from the body of the response, use Response Values. Although the XML or JSON Query Service has some limited capabilities for automatically parsing values from XML responses using XPath expressions, in most cases you will parse the response in Javascript. 

To parse your response in Javascript, set the Response Type field to “RAW”, set Response Values to 1 and, under #1, set Variable to the name of the variable that will hold the response, and set the Path to “/” indicating you want the entire response in that variable. (If your response format is XML, you can set the Response Type to “XML” and put XPath expressions in the Path field to parse individual values from the XML response into variables.)

The screenshot below shows the XML or JSON Query Service configured to set the Response’s HTTP status code and description in the apiStatusCode and apiStatusDescription variable respectively, and set the response body in the apiResponse variable, before calling the block’s events:

The Javascript that you will use in your event to parse the response depends on the response structure, so let’s use the following JSON as an example:

{
    "name":"John",
    "age":30,
    "cars": [
        "Ford",
        "BMW",
        "Fiat"
    ]
}


Let’s say that we receive this response back from an API, and we want to set EachScape variables called userName, userAge, userCar1, userCar2 and userCar3 based on the values in the response. We can go to our XLM or JSON Query Service’s Success event and enter the following Javascript code (Tip: if you haven’t added any actions to the Success event yet, click Start with Javascript in the top right corner of the Action selector to write your event handler using Javascript):

// First, get the API response body as a javascript variable
ESLib.getVarAsync('apiResponse'). // <-- This is the Variable we set for the Response
then((responseBody) => {

      // responseBody has the JSON response as a string, so we need to parse it:
      let responseData = JSON.parse(responseBody);

      // Now we can access values in the JSON body in the usual manner:
      ESLib.setVar('userName', responseData.name);
      ESLib.setVar('userAge', responseData.age);

      // We need to iterate over the cars array to get the 3 car values:
      for(let i = 0; i < responseData.cars.length; i++) {
        // In the variable name, we add i+1 to the end of the string "userCar" since i
        // starts at 0 but we want our variables to be called userCar1, userCar2 and userCar3
        ESLib.setVar('userCar' + i + 1, responseData.cars[i]);
      }
    }
);