5

I am have created an external service using the integrations beta feature in Salesforce. You can use the Apex actions created by this service in Flow.

The problem that I am facing is that Apex call out actions return multilevel Json something like below. I am not sure how to read/Parse this in a Flow. Any suggestions would be highly appreciated.

{
    "data": {
        "bearer": "MiVNZxO2TSudewmuvtPSqEgY7HM",
        "refresh": "Ce8myNoHl3q1Ld0eXqrFZx4iAksh87BN",
        "bearerExpiredInSeconds": 1799,
        "refreshExpiredInSeconds": 3599,
        "passwordResetRequired": false
    }
}
5
  • This might help you parsing. shrutisridharan.wordpress.com/2018/02/12/… Commented Apr 26, 2018 at 13:33
  • Thanks Pranay, in the link provided the jason response is simple, It just returns one level of JSON, My questions is what if the JSON returned has a hierarchy of multiple levels. Refer to the question and example JSON that I provided. If I have to read the value associated with "bearer" then how can I read it in Flow.
    – Sam
    Commented Apr 26, 2018 at 14:03
  • You can send this JSON string to an APEX class. Parse the JSON in APEX and return parsed response from APEX back to flow. Commented Apr 26, 2018 at 18:59
  • Did you check out the new option with Apex-Defined Data Type? So the apex will parse it for you and you could use it in your flow as a regular object help.salesforce.com/…
    – MenashYA
    Commented Mar 9, 2020 at 10:40
  • As of 2021, consider adding this Datamapper extension, which takes JSON and lets you convert it to Flow resources. unofficialsf.com/… Commented Aug 11, 2021 at 15:52

4 Answers 4

3

I'm late to answering this, but for anyone looking for a simple Apex flow action, here is a (limited) solution:

Apex Class:

global class ReadJson {
    @InvocableMethod(label = 'Read JSON')
    global static List<JsonResponseVariables> ReadJson(List<JsonParserRequest> requests){
        List<JsonResponseVariables> responses = new List<JsonResponseVariables>();
        for(JsonParserRequest req : requests){
            responses.add(ParseAndSaveJsonFields(req));
        }
        return responses;
    }

    public static JsonResponseVariables ParseAndSaveJsonFields(JsonParserRequest request){
        JsonResponseVariables response = new JsonResponseVariables();
        Map<String, Object> json = (Map<String, Object>) JSON.deserializeUntyped(request.jsonDoc);
        if(!String.isBlank(request.keyValue1)){
            if(KeyExists(request.keyValue1, json)){
                response.jsonVal1 = (String)String.valueOf(json.get(request.keyValue1));
            } else {
                throw new readJsonException('Cannot find key ' + request.keyValue1 + ' in provided JSON document. Make sure the key is valid and the desired element is located on the root level of the document.');
            }
        }
        return response;
    }

    public static Boolean KeyExists(String key, Map<String, Object> jsonObj){
        if(jsonObj.containsKey(key)){
            return true;
        } 
        return false;
    }

    public class readJsonException extends Exception {}



    global class JsonParserRequest {
        @InvocableVariable(label='JSON Doc' description='The JSON Doc to parse')
        public String jsonDoc;

        @InvocableVariable(label='Key/Value to Exract 1' description='The key used to extract the desired value')
        public String keyValue1;
    }

    global class JsonResponseVariables {
        @InvocableVariable(label='Json Value 1' description='Returns the first value specified from the JSON')
        public String jsonVal1;
    }
}


In short, this class will allow a user to Parse a simple JSON doc (1 level only). Additionally this class can only parse one key at a time For example, I have a platform event that sends a simple json like this:

{
    recordId: "123456789",
    count: 15
}

Using the image below you can see how I could parse that JSON string to retrieve the value within the count key. I could perform that same apex action again, but pass the recordId key to also retrieve the value within that key.

Image displaying the apex class in use

Overall this isn't the greatest solution, but it does offer a Salesforce admin some ability to handle JSON docs from a flow without having to touch any code.

2
  • I like this, Tyler. Here's another approach: unofficialsf.com/…. The UnofficialSF community is always looking for invocable action developers to join our efforts! =] Commented Aug 11, 2021 at 15:54
  • @AlexEdelstein Oh yeah that mapper is a much more dynamic approach! And any way I could be of assistance in the UnofficialSF community, I would love to do so! Commented Aug 26, 2021 at 18:56
3

Belated answer, in case others come back to this.

This answer only works if the JSON you're dealing with is approximately as simple as the one you gave as an example. But if so, you could consider doing string manipulation in the flow with a formula.

e.g.

TRIM(
    SUBSTITUTE(
        SUBSTITUTE(
            MID(
                {!json}, 
                FIND('"bearer": "',{!json}) + LEN('"bearer": "'),
                (
                    FIND('"refresh"',{!json}) -
                    (FIND('"bearer": "',{!json}) + LEN('"bearer": "'))
                )
            ), 
            '"', ''
        ), 
        ',', ''
    )
)

If you use that formula on the example you gave, you get MiVNZxO2TSudewmuvtPSqEgY7HM.

That formula is kinda complex and hard to parse. Basically it says, "give me the part of the JSON string that comes in between "bearer": " and "refresh", then remove all remaining quotation marks, commas, and extra whitespace."

This is the kind of situation where these days, I would normally ditch Flow and go with Apex. But there was a time when I was afraid of code and learned to write stuff like what you see above.

If you're a dyed-in-the-wool clicks-not-code developer, let me entice you with proof that sometimes code is easier:

2

As of 2021, consider adding this Datamapper extension, which takes JSON and lets you convert it to Flow resources.

1

Here is a possible approach to solve your issue. I don't think there is any short way of parsing JSON directly in Flows.

  • Pass JSON string as a parameter to Invocable method of a public apex class.

  • Parse that JSON to some public or global class implementing the structure as in your JSON. You can use JSON.desrialize to parse your JSON. Make sure your structure class contains at least one member variable with the invocable variable annotation.

  • Return the deserialized value back to apex. Keeping return type of invocable method as your structure class.

  • Save the returned value into a flow variable and utilise as you need.

Refer given link for extra information on flows and invocable apex methods: invocable apex annotation

Hope this helps you. Please mark as correct answer if this is helpful.

2
  • Thanks Ashish, But invocable methods return List, How do I handle List in Flow.
    – Sam
    Commented Apr 26, 2018 at 23:41
  • You can use collection type flow variable. Collection type can hold list of primitive, sObjects or user defined data type. Go through the link given in answer and you will find how to store list into a flow variable. Commented Apr 27, 2018 at 2:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .