Loading
Prepare for Email to Become the Default Login ExperienceRead More
Custom Input and Output for Omnistudio Data Mappers in Omnistudio

Custom Input and Output for Omnistudio Data Mappers in Omnistudio

By default, Data Mappers handle JSON and XML data. To handle other data formats, you can configure a Data Mapper to use a custom input or output that you implement is a custom class. For example, you can define a Data Mapper Transform that accepts CSV-formatted data and outputs it as JSON.

Options are as follows:

  • Data Mapper Load: Custom input (output is always a Salesforce object)

  • Data Mapper Transform: Custom input and output

  • Data Mapper Extract: Custom input and output

To configure a Data Mapper to use a custom input or output, set its type to Custom. Then specify the class that contains the serialize and deserialize methods that perform the operation. The following table shows properties for a Data Mapper Transform configured with a custom input and output.

Property Value
Data Mapper Interface Name Custom Serialization Transform
Interface Type Transform
Input Type Custom
Custom Input Class CSVProcessor
Output Type Custom
Custom Output Class CSVProcessor

For ease of mapping, you can paste sample input into the Expected Input and Expected Output panes.

To create the logic required to custom input and output, you must define a custom class that implements Callable. For custom output, implement the serialize method. For custom input, implement the deserialize method. You can’t rename the input and output parameters.

The following example shows the basic structure of a customer serialization and deserialization class.

global with sharing class PreprocessorClassExample implements Callable {
   public Object call(String action, Map<String, Object> args) {

        Map<String, Object> input = (Map<String, Object>)args.get('input');
        Map<String, Object> output = (Map<String, Object>)args.get('output');
        Map<String, Object> options = (Map<String, Object>)args.get('options');

        return invokeMethod(action, input, output, options);
    }
    private Object invokeMethod(String methodName, Map<String,Object> input, Map<String,Object> output, Map<String,Object> options) {
        if (methodName == 'serialize') {
            return serialize(input, output);
        }
        else if (methodName == 'deserialize') {
            return deserialize(input, output);
        }
        return false;
    }
    /*
        Serializes Apex objects into JSON content. Return String json
    */
    global Boolean serialize(Map<String, Object> input, Map<String, Object> output) {
        String jsonString = '';            
        // code
        output.put('output', jsonString); // JSON String
        return true;
    }
    /*
        Deserializes the specified JSON string into collections of primitive data types. Return Object ((Map<String, Object>))
    */
    global Boolean deserialize(Map<String, Object> input, Map<String, Object> output) {
        Map<String, Object> returnMap = new Map<String, Object>();
        // code
        output.put('output', returnMap); // ---> collections of primitive data types Map<String, Object>, List<Map<String, Object>>()
        return true;
    }
}

The following example serializes and deserializes CSV data.

global with sharing class CSVProcessor implements Callable {
    public Object call(String action, Map<String, Object> args) {

        Map<String, Object> input = (Map<String, Object>)args.get('input');
        Map<String, Object> output = (Map<String, Object>)args.get('output');
        Map<String, Object> options = (Map<String, Object>)args.get('options');

        return invokeMethod(action, input, output, options);
   }
   private Object invokeMethod(String methodName, Map<String,Object> input, Map<String,Object> output, Map<String,Object> options)
   {
   System.debug('METHOD NAME >>> ' + methodName);
       if (methodName == 'deserialize')
       {
           return deserialize(input, output);
       }
       return false;
   }
   /*
   Example Output: 'Column2,Column1\nvalue0,value1.0\nvalue0.1,value1.1';
   */
   /*
   Deserializes the specified JSON string into collections of primitive data types. Return Object ((Map<String, Object>))
   Input: 'Column2,Column1\nvalue0,value1.0\nvalue0.1,value1.1';
   Output:
   [
       {
           "Column1Test": "value1.0",
           "Column2Test": "value0"
       },
       {
           "Column1Test": "value1.1sl",
           "Column2Test": "value0.1"
       }
   ]
   */
        public class csvInput {
            @AuraEnabled
            public string VersionData;
        }
        global Boolean deserialize(Map<String, Object> input, Map<String, Object> output)
   {
       System.debug(input);
       System.debug(input.get('input'));
       System.debug(input.toString());
       //csvInput s = (csvInput)JSON.deserialize((string)input.get('input'), csvInput.class);
       Object data = input.get('input');
       csvInput s;
       if(data instanceof String) {
           s = (csvInput)JSON.deserialize(String.valueOf(data), csvInput.class);
       } else { // try to preserve the source formatting
           s = (csvInput)JSON.deserialize(JSON.serialize(data), csvInput.class);
       }
       Blob decodedInputBlob = System.EncodingUtil.base64Decode(s.VersionData);
       String decodedCsvString = decodedInputBlob.toString();
       Object inputValue = decodedCsvString;
       System.debug(inputValue);
       if (inputValue != null && inputValue InstanceOf String)
       {
           List<String> valueSet = ((String)inputValue).split('\n');
           List<Map<String, String>> csvList = new List<Map<String, String>>();
           List<String> columns = new List<String>();
           for (Integer i = 0; i < valueSet.size(); i++)
           {
               String value = valueSet[i];
               if (String.isBlank(value))
               {
                   continue;
               }
               if (i == 0)
               {
                   List<String> valSet = value.split(',');
                   for (Integer y = 0; y < valSet.size(); y++)
                   {
                       columns.add(valSet[y]);
                   }
               }
               else
               {
                   List<String> valSet = value.split(',');
                   if (columns.size() >= valSet.size())
                   {
                       Map<String, String> rows = new Map<String, String>();
                       for (Integer z = 0; z < valSet.size(); z++)
                       {
                           rows.put(columns[z], valSet[z]);
                       }
                       csvList.add(rows);
                   }
               }
           }
           output.put('output', csvList);
           //Map<String, Object> returnMap = new Map<String, Object>();
           //output.put('output', returnMap);
           System.debug(output);
           return True;
       }
       return False;
   }
}

For example, suppose your CSV file has this content:

Name

Email

Phone

Mary Baker

mbaker@example.com

415-555-3331

Joe Baker

jbaker@example.com

415-555-3332

Russell Baker

rbaker@example.com

415-555-3333

The example CSVProcessor class converts it to this JSON input:

[
  {
    "Name": "Mary Baker",
    "Email": "mbaker@example.com",
    "Phone": "415-555-3331"
  },
  {
    "Name": "Joe Baker",
    "Email": "jbaker@example.com",
    "Phone": "415-555-3332"
  },
  {
    "Name": "Russell Baker",
    "Email": "rbaker@example.com",
    "Phone": "415-555-3333"
  }
]
 
Loading
Salesforce Help | Article