Powered By Blogger

Aug 29, 2016

Using a Class Mediator to process JSON payload

 

This blog post describes about using a class mediator to process  JSON payload

sample JSON:

{
   "query": "InformationSystem[@id\u003d\"22174\"]",

   "result": [
    {
      "id": [
        "22174"
      ],
      "description": [
        "test 123"
      ],
      "Application Type": [
        "Sample Application"
      ],
      "{Sample} ID": [
        "ID1"
      ]
    }
  ]
}



You can use WSO2 Developer Studio to create a mediator project and since I have used jackson as the library I have added below dependencies to the pom.xml of the mediator project

         <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.7.2</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.7.2</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.2</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-asl</artifactId>
            <version>1.9.3</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.synapse</groupId>
            <artifactId>synapse-commons</artifactId>
            <version>2.1.2-wso2v4</version>
        </dependency>



The code is as follows:

package org.wso2.sample;

import java.util.Iterator;
import java.util.Map;

import org.apache.synapse.MessageContext;
import org.apache.synapse.commons.json.JsonUtil;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.apache.synapse.mediators.AbstractMediator;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;

public class JSONClassMediator extends AbstractMediator {

    public static final String RESULT_NODE = "result";
    public static final String QUERY_NODE = "query";

    @SuppressWarnings("deprecation")
    public boolean mediate(MessageContext context) {
        try {
            // Getting the json payload to a string
            String jsonPayloadToString = JsonUtil.jsonPayloadToString(((Axis2MessageContext) context)
                    .getAxis2MessageContext());

            JsonFactory factory = new JsonFactory();
            ObjectMapper mapper = new ObjectMapper(factory);

            JsonNode rootNode = mapper.readTree(jsonPayloadToString);
            //create a new root object
            ObjectNode rootObject = mapper.createObjectNode();
           
            //process query node
            TextNode queryNodeValue = (TextNode) rootNode.get(QUERY_NODE);
            rootObject.put(QUERY_NODE, queryNodeValue.asText());
           
            //process result node
            ArrayNode resultNode = (ArrayNode) rootNode.get(RESULT_NODE);
            JsonNode resultChildNode = ((ArrayNode) resultNode).get(0);
            Iterator<Map.Entry<String, JsonNode>> fieldsIterator = resultChildNode.fields();
            ObjectNode newNode = mapper.createObjectNode();
            ArrayNode resultArray = mapper.createArrayNode();
            while (fieldsIterator.hasNext()) {
                Map.Entry<String, JsonNode> field = fieldsIterator.next();
                String newKey = field.getKey().replace(" ", "-").replace("{", "").replace("}", "").replace("%", "");
                newNode.put(newKey, field.getValue());
            }          
            resultArray.add(newNode);
            rootObject.put(RESULT_NODE, (JsonNode) resultArray);
       
            // Setting the new json payload.
            String transformedJson = rootObject.toString();
            JsonUtil.newJsonPayload(((Axis2MessageContext) context).getAxis2MessageContext(), transformedJson, true,
                    true);

        } catch (Exception e) {
            handleException("error in processing the json payload", e,context);
            return false;
        }

        return true;
    }
}


Proxy configuration is as follows:

<?xml version="1.0" encoding="UTF-8"?>
       name="sampleProxy"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <call>
            <endpoint key="conf:/repository/sampleEP"/>
         </call>
         <class name="org.wso2.sample.JSONClassMediator"/>
         <log level="full">
            <property name="************RESULT************" expression="$body"/>
         </log>
      </inSequence>
   </target>
   <description/>
</proxy>
 
 
Result:
 
<jsonObject>
      <query>InformationSystem[@id="22174"]</query>
      <result>
         <id>22174</id>
         <description>test 123</description>
         <Application-Type>Sample Application</Application-Type>
         <Sample-ID>ID1</Sample-ID>
      </result>
  </jsonObject>

Using a Script Mediator to process JSON payload


This blog post describes about using a script mediator to process  JSON payload

usecase:

When the JSON payload has spaces and special characters for element names, then replace those spaces and characters as required

sample JSON:

{
  "result": [
    {
      "id": [
        "22174"
      ],
      "description": [
        "test 123"
      ],
      "Application Type": [
        "Sample Application"
      ],
      "{Sample} ID": [
        "ID1"
      ]
    }
  ]
}


Please follow below steps:

1. In the proxy service configuration, first you need to assign the JSON payload to a property as below, (this will assign the array inside the 'result')

       <property name="JSONPayload" expression="json-eval($.result[0])" />
      
2. Then define the script mediator as below

       <script language="js" key="conf:/repository/transform.js" function="transform" />
      
based on this you need to create a registry resource (.js) in the registry ( eg: at conf:/repository/) and need to add the js script into that file

3. In this sample we are going to remove the spaces and curly braces from the elements, hence we have used below script.

function transform(mc) {
    var obj = mc.getProperty('JSONPayload'); //gets the property from the message context
    var jsonObject = JSON.parse(obj); // casting the json string to a json object

    var jsonArray = {
        result: []     // initializing the array
    };
    var item = {}
    for (var prop in jsonObject) {
        var attrName = prop;
        var att = attrName.replace(/ /g, '');  //replacing white spaces
        var att = att.replace(/[{}]/g, ""); //replacing curly braces
        var attrValue = jsonObject[prop];
        var jsonText = JSON.stringify(att);
        item[att] = attrValue;
    }
    jsonArray.result.push(item); //adds the sanitized json to the defined array
    mc.setPayloadJSON(jsonArray); //set the created json payload to the message context
 }



Please find the below complete proxy configuration as a reference

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="sampleProxy" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
   <target>
      <inSequence>
         <call>
            <endpoint key="conf:repository/sampleEP" />
         </call>

         <property name="JSONPayload" expression="json-eval($.result[0])" />
         <script language="js" key="conf:/repository/transform.js" function="transform" />
           <log level="full">
            <property name="************RESULT************" expression="$body" />
         </log>
      </inSequence>
   </target>
   <description />
</proxy>


Final result will be as below:


<jsonObject xmlns="http://ws.apache.org/ns/synapse">
   <result>
      <id>22174</id>
      <description>test 123</description>
      <ApplicationType>Sample Application</ApplicationType>
      <SampleID>ID1</SampleID>
   </result>
</jsonObject>



Script Mediator - https://docs.wso2.com/display/ESB481/Script+Mediator
JSON support in ESB - https://docs.wso2.com/display/ESB481/JSON+Support