1

I am looking to create a slack payload. I am struggling to create this payload in Apex.

{
        "username": "Bot Name",
        "text": "*Call Recording* :tada:",
        "attachments":[
            {
            "author_name": "Dean",
            "title": "Call Recording",
            "title_link": "https://api.slack.com/",
            "color": "#36a64f",
             "fields": [
                    {
                        "title": "Account",
                        "value": "var",
                        "short": true
                    },
                 {
                        "title": "Contact",
                        "value": "var",
                        "short": true
                 }
                 ]
             }

        ],
        "icon_emoji": ":dromedary_camel:"
    }

So far I have created the following:

JSONGenerator gen = JSON.createGenerator(true);
            gen.writeStartObject(); //Inserts {
            gen.writeStringField('channel', r.channel);
            gen.writeStringField('icon_emoji', ':dromedary_camel:'); 
            gen.writeStringField('username', r.bot_username_var);
            gen.writeStringField('text', r.title_var);
            gen.writeFieldName('attachments');
                gen.writeStartArray();
                    gen.writeStartObject();

                        gen.writeStringField('author_name', r.rep_var);
                        gen.writeStringField('title', r.call_recording_title_var);
                        gen.writeStringField('title_link', r.call_recording_title_var);
                        gen.writeStringField('color', '#36a64f');
                        gen.writeFieldName('fields');
                        gen.writeStartArray();
                            gen.writeStartObject();
                                gen.writeStringField('title', 'Account');
                                gen.writeStringField('value', r.account_var);
                                gen.writeStringField('short', true);
                            gen.writeEndObject();
                            gen.writeStartObject();
                                gen.writeStringField('title', 'Contact');
                                gen.writeStringField('value', r.contact_var);
                                gen.writeStringField('short', true);
                            gen.writeEndObject();

                        gen.writeEndArray();

                    gen.writeEndObject();
                gen.writeEndArray();
            gen.writeEndObject(); //Inserts }

            String body = gen.getAsString(); //Translates JSONGenerator to string to be passed to callout
5
  • 1
    This might help -- json2apex.herokuapp.com
    – kurunve
    Jul 10, 2019 at 18:37
  • Wow, there has to be an easier way Jul 10, 2019 at 18:40
  • 4
    Don't ever use JSONGenerator. It is slow, more complicated, and usage of it leads to more complicated or lower value tests.
    – Adrian Larson
    Jul 10, 2019 at 19:33
  • @AdrianLarson so what would you recommend? Jul 10, 2019 at 19:53
  • 1
    Use the built in JSON.serialize and JSON.deserialize methods. Create a class to model your data structure so that you can use that for the target/source of those methods.
    – Adrian Larson
    Jul 10, 2019 at 20:15

1 Answer 1

4

The simplest way for you to do this is to leverage a custom class, like so:

Classes (you can put them all inside of a larger class, or keep them as individual Apex Classes

public class mySlackPayload {
  public String username;
  public String text;

  public List<mySlackAttachment> attachments;
  <the rest of your props go here>

}

public class mySlackAttachment {
  <attachment props go here>
}

Then, in your current code, you can do this

mySlackPayload myPayload = new mySlackPayload();
myPayload.username = 'xxx';
<fill the rest of the props>

String serializedPayload = JSON.serialize(myPayload);

Doing this with sObjects will add extraneous properties added by Apex that will mess up that payload un-necessarily. You can also add constructors to those classes to take an sObject as a parameter and populate properties accordingly.

PS: The tool described in comments by @kurunve should generate this custom class for you (I admit I find the result of that class a bit bloated), then you would simply use the second part of my code to populate and call it.

8
  • Should I look into the JSONGenerator class? JSONGenerator gen = JSON.createGenerator(true); Jul 10, 2019 at 19:15
  • 1
    I don't think it makes sense. When you serialize a class it'll come out neat as you specified in your original post. But you have to build that class first to mimic the JSON output you want Jul 10, 2019 at 19:19
  • why are you doing JSON.serialize(mySlackPayload) I thought you would do JSON.serialize(myPayload) Jul 10, 2019 at 19:54
  • 1
    Oh, that is correct, and a typo. Fixing that. Jul 10, 2019 at 19:58
  • 1
    @MatthewMetros - seconding Sebastian's solution as that is what I did for my Slack integration with one exception - I added a toJson() method on MySlackPayload class to make it a bit more OO
    – cropredy
    Jul 10, 2019 at 20:56

You must log in to answer this question.

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