2

I am trying to POST JSON content to an API endpoint. To do this I have done the following,

// When tracking leads being created, get the Lead Id, Email, name, age, and Agency type fields 
List<Lead> leadsToTrack = [SELECT Email, First_Name__c, Last_Name__c , lead_ag__C, Agency_Type__c  FROM Lead WHERE Id in :leads]; 

    if (leadsToTrack.size() > 0) 
{sendRequest(JSON.serialize(leadsToTrack), '/v3/contactdb/recipients', 'POST');

    system.debug(leadsToTrack);

How ever the formatting provided by JSON.serialize is not acceptable by the reciever.

This is how it comes out.

[{"attributes":{"type":"Lead","url":"/services/data/v40.0/sobjects/Lead/00Qf4000001Y30kEAC"},"Email":"goosyssg@facebosok.com","lead_ag__c":0,"Id":"00Qf4000001Y30kEAC"}]

This is what is expected plus a couple of fields not in this example.

 [{"email":"example@example.com","first_name":"sam","last_name":"User","age":22},{"email":"example2@example.com","first_name":"Example","last_name":"test","age":10}]

In this post it is said that I need to use the JSON generator to get custom formatting, so I wrote this,

public class JSONgen {

static void generateJSONContent(string eMail, string last, string first, string age, string market, string atype) {
    // Create a JSONGenerator object.
    // Pass true to the constructor for pretty print formatting.
    JSONGenerator gen = JSON.createGenerator(false);

    // Write data to the JSON string.
    gen.writeStartArray();
    gen.writeStartObject();
    gen.writeObjectField('Email', eMail);
    gen.writeObjectField('last_name', last);
    gen.writeObjectField('first_name', first);
    gen.writeObjectField('type', atype);
    gen.writeObjectField('age', age);

    gen.writeEndObject();
    gen.writeEndArray();



    // Get the JSON string.
    String pretty = gen.getAsString();

system.debug(pretty);
}
}

When I run it I get an error, but the real question is, how do this in mass for a bunch or leads at a time? I am new to salesforce, didn't know it existed til april, and I started learning apex 10 days ago so give me some slack for the noob status. The end goal is to update an external server for every new lead, and daily update leads meeting set criteria. The only issue I am having that I know of is passing properly formatted data, All help we be appreciated and I thank you in advance for your time.

2

I find the simplest way to build specific format JSON is often to just use lists and maps. That gives you full control over the names used including allowing names that are not legal field names in Apex classes (such as wrapper classes). The JSON.serialize method then does all the hard work of respecting the structure you have created.

So for your example:

List<Map<String, Object>> mm = new List<Map<String, Object>>();
for (Lead l : [
        SELECT Email, First_Name__c, Last_Name__c ,lead_ag__C, Agency_Type__c
        FROM Lead
        WHERE Id in :leads
        ]) {
    Map<String, Object> m = new Map<String, Object>{
        'email' => l.Email,
        'first_name' => l.First_Name__c,
        ...
    };
    mm.add(m);
}

String jsonString = JSON.serialize(mm);
sendRequest(jsonString, '/v3/contactdb/recipients', 'POST');
| improve this answer | |
4

I have never found use for JSONGenerator. It is almost always more straightforward and performant to just use the built in serialize/deserialize functionality. You just need a wrapper class here:

public with sharing class Recipient
{
    public final String email, first_name, last_name;
    public final Integer age;
    public Recipient(Lead record)
    {
        email = record.Email;
        first_name = record.FirstName;
        last_name = record.LastName;
        age = (Integer)record.lead_ag__c; // note the misspelling
    }

    public static List<Recipient> factory(List<Lead> records)
    {
        List<Recipient> recipients = new List<Recipient>();
        for (Lead record : records) recipients.add(new Recipient(record));
        return recipients;
    }
}

Make sure you add the fields you need to your query! Now this payload should match your desired format:

String payload = JSON.serialize(Recipient.factory([
    SELECT Email, FirstName, LastName, Lead_Ag__c FROM Lead WHERE ...
]));
| improve this answer | |
  • 2
    A related tip: If you find yourself wanting to serialize an Apex class, but you don't want to serialize all of the class variables, you can add the transient keyword to the declaration of a class variable. The main use of that keyword is to keep things out of the viewstate for Visualforce, but JSON.serialize() will also ignore things marked as transient. – Derek F Aug 30 '17 at 17:38
  • Forgive me, but it's not immediately apparent how I am to implement this 'wrapper class' into my code. Should I post the full class I am working on and the trigger that initiates the process? – Roger Morris Aug 30 '17 at 18:21
  • 1
    @RogerMorris Adrian's example should be pretty much copy/paste. Recipient would be another Apex class that you would create. Adrian's second code snippet would take the place of everything in the first snippet of code that you provided. The only thing missing is you'd need to send the String variable payload to your sendRequest() method. – Derek F Aug 30 '17 at 20:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.