6

I have created a REST Endpoint (exposed on force.com site) to allow Webhook messages.

The third party service will POST data to the webhook that looks like this:

Body:

{
  "channel": "server",
  "email": "[email protected]",
  "messageId": "test-message-37q7z9",
  "projectId": "oYOQY8rnYw",
  "replay": true,
  "timestamp": "2018-12-04T16:22:37.195Z",
  "traits": {
    "trait1": 1,
    "trait2": "test",
    "trait3": true
  },
  "type": "identify",
  "userId": "test-user-x1nyrr"
}

How can I read the attributes in the traits object? (i.e. trait1, trait2). I should note the attributes in the traits object may increase/decrease in size so this needs to be somewhat dynamic.

This is what I have so far but I'm not sure how to parse the payload.

@RestResource(urlMapping='/webhook')
global class WebhookReq {

    @HttpPost
    global static String doPost() {
        //Blob name = RestContext.request.params.get('name');
        String traits = RestContext.request.params.get('traits');
        RestRequest req = RestContext.request;
        String result = JSON.deserialize(req.getBody());

        return result;
    }

}

2 Answers 2

8

Since the types can be mixed, you need to use either the JSONParser (I would not recommend this) or JSON.deserializeUntyped. Here's the latter method:

Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(
  RestContext.request.requestBody.toString()
);
Map<String, Object> traits = (Map<String, Object>)params.get('traits');
for(String key: traits.keySet()) {
  Object value = traits.get(key);
  if(value instanceof integer) {
    ...
  } else if(value instanceof string) {
    ...
  } else if(value instanceof boolean) {
    ...
  }
}

Since I don't know what you intend to do with this, I can't really write more, but at this point, you should have everything you need.

4
  • May I know why why you don't recommend JSONParser?
    – NBR
    Commented Dec 28, 2021 at 8:10
  • 1
    @NBR It has terrible performance characteristics, is difficult to use correctly, and usually requires writing more code than any other means of parsing JSON. I have literally used it exactly zero times in any code I've written for any project since I started writing Apex code in 2007.
    – sfdcfox
    Commented Dec 28, 2021 at 9:03
  • Thanks.! How to get the value of object field? I am getting runtime error if I try to use obj.Name. Is there a way without creating a class? Something like obj.get('name' ). obj.get('industry')? This is not a sObject.
    – NBR
    Commented Dec 28, 2021 at 13:50
  • @NBR See this Q&A and others in our canonical-qa tag that speak about JSON parsing. We've got a lot content available on this topic.
    – sfdcfox
    Commented Dec 28, 2021 at 15:15
3

You can use deserializeUntyped(jsonString) here as below. Refer to the example details on the documentation.

Map<String, Object> myMap = (Map<String, Object>) JSON.deserializeUntyped(req.getBody().toString());
Map<String, Object> traitsMap =  (Map<String, Object>)myMap.get('traits');

for(Integer i = 1; i < traitsMap.size(); i++) {
    system.debug(traitsMap.get('traits'+i)); // will print the value of traits<i>
}

You must log in to answer this question.

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