com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links' is unknown.

JSON Mapping

JSON mapping support in data services is available as another result type in the output mappings section of the data services query. That is, you can specify JSON as the output type for the query and then provide the JSON template that should be used for service responses. 

From DSS version 3.2.0 onwards, the default JSON message formatter/ builder is implemented based on org.apache.axis2.json.gson, which supports some new features as explained below.

Basic Mapping

The following is a sample JSON mapping of the data services results. Here, we can see the JSON template, which is the format that is expected to be returned from our query. 

Sample JSON Mapping
{
    "customers": {
        "customer": [
            {
                "phone": "$phone",
                "city": "$city",
                "contact": {
                    "customer-name": "$customerName",
                    "contact-last-name": "$contactLastName",
                    "contact-first-name": "$contactFirstName"
                }
            }
        ]
    }
}

As shown in the sample given above, the column name values that are expected in the query result should be referred to by the column name with the "$" prefix. E.g. "$customerName".

Also, the structure of the JSON template should follow some guidelines in order to be compatible with the result. These guidelines are:

  • The top most item should be a JSON object. It cannot be a JSON array.
  • For handling multiple records from the result set, the immediate child of the top most object can be a JSON array, and the array should contain only a single object.
  • If only a single result is returned, the immediate child of the top most object can be a single JSON object.
  • After the immediate child of the top most object, there cannot be other JSON arrays in the mapping.

All JSON responses will be returned as an array.

Extended Properties for Mapping Fields

In a basic JSON output mapping, we specify the field values that we expect in the query result. You can give additional properties to this field mapping, such as data type of the field, the possible content filtering user roles etc. These extended properties for the fields are given in parentheses, with a list of string tokens providing the additional properties, separated by a semi colon (";").

Data Types

The example given below shows how the 'data type' property is added to the 'age' field using parentheses "()".

JSON Mapping with Data Types
{ "age" : "$age(type:integer)" }
  • The extended property 'type' is given along with the value 'integer'. 
  • The property and the value are separated by a colon. 
  • Note that the possible values for data type are "integer", "long", "double" and "boolean".

Content Filtering (Required Roles)

The example given below shows how the 'data type' extended property as well as the 'required roles' extended property is added to the 'age' field using parentheses "()".

JSON Mapping with Required Roles
{ "salary" : "$salary(type:double;requiredRoles:hr,admin)" }
  • The 'requiredRoles' property is added along with the values 'hr' and 'admin'. 
  • Note that the two values for required roles property are separated by a comma. 
  • Also, the two extended properties are separated by a semicolon. 

Nested Queries

Nested queries can be mentioned in the JSON mapping by giving the query details as a JSON object attribute. That is, the name of the target query to be called and the property value (the fields in the result mapped with the target query parameters) are included in the JSON mapping as the object attribute name. Example:

JSON Mapping with Nested Queries
{
    "Offices": {
        "Office": [
            {
                "officeCode": "$officeCode(type:integer)",
                "city": "$city",
                "country": "$country",
                "phone": "$phone",
                "@employeesInOfficeSQL": "$officeCode->officeCode"
            }
        ]
    }
}

In the nested query mapping,

  • The target query name is mentioned by prefixing the query name with "@". Note "@employeesInOfficeSQL" in the example given above.
  • The parameter mapping is added to the query by giving the following values: The field name in the result prefixed by "$", and the name of the target query parameter.
  • These two values in the parameter mapping are separated by "->". See "$officeCode->officeCode" in the example given above.
  • Note that the target query name and the parameter mapping are separated by a colon as follows: "@employeesInOfficeSQL": "$officeCode->officeCode"

JSON Request Payloads

In sending JSON request payloads for data services REST resources, the JSON payload must be in a specific format for different types of HTTP methods.

HTTP POST

When you send an HTTP POST request, the format of the JSON object name should be "_post$RESOURCE_NAME", and the child name/values of the child fields should be the names and values of the input parameters in the target query. Given below is an example of a JSON request that sends an HTTP POST request to the "employee" resource path. 

JSON Request for Data Service REST Resource with HTTP POST
{
  "_postemployee": {
    "employeeNumber" : 1,
    "lastName": "Doe",
    "firstName": "John",
    "email": "jdoe@wso2.com",
    "salary": 13500.0
  }
}

HTTP PUT

When you send an HTTP PUT request, the format of the JSON object name should be "_put$RESOURCE_NAME", and the child name/values of the child fields should be the names and values of the input parameters in the target query. Given below is an example of a JSON request that sends an HTTP PUT request to the "employee" resource path. 

JSON Request for Data Service REST Resource with HTTP POST
{
  "_putemployee": {
    "employeeNumber" : 1002,
    "lastName": "Smith",
    "firstName": "Will",
    "email": "will@smith.com",
    "salary": 86500.0
  }
}

Data Service JSON based Resource Batch Requests

When batch requests are enabled for data services resources, it creates corresponding resource paths with the "_batch_req" suffix. And in the payload content, the single request JSON object becomes a one of the possibly many objects in a parent JSON array object with a name single request wrapper object + "_batch_req". The following contains a sample batch request for the earlier HTTP POST request example.

JSON Request for a Batch Data Service Resource Execution
{
    "_postemployee_batch_req": {
        "_postemployee": [
            {
                "employeeNumber": 5012,
                "lastName": "Smith",
                "firstName": "Will",
                "email": "will@smith.com",
                "salary": 13500.0
            },
            {
                "employeeNumber": 5013,
                "lastName": "Peter",
                "firstName": "Parker",
                "email": "peter@parker.com",
                "salary": 15500.0
            }
        ]
    }
}

A JSON Mapping Sample in WSO2 Data Services Server can be found here: JSON Mapping Sample.

JSON Mapping in tenant mode

To run this feature in tenant mode, remove the following content in the axis2.xml and tenant-axis2.xml files.

<messageBuilder contentType="application/json"  class="org.apache.axis2.json.gson.JsonBuilder" />
<messageFormatter contentType="application/json"   class="org.apache.axis2.json.gson.JsonFormatter" />

Then, uncomment the following content in the same files.

<messageFormatter contentType="application/json"   class="org.apache.axis2.json.JSONMessageFormatter"/>
<messageBuilder contentType="application/json"    class="org.apache.axis2.json.JSONOMBuilder"/>
com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.