function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
ekorzekorz 

Serialize Child record(s), create JSON body

Hello!

 

I'm pretty new to JSON methods so forgive me if this doesn't make 100% sense...


I built an Apex class that passes JSON data from Salesforce to Netsuite.  I call the class from a Button (javascript) on a Parent record.  All works fine.

 

Before, I was just building the JSON Body manually before (code below) since it seemed easy at the time.  Now, I've got to figure out a way to query the Parent's Child records, serialize those children into the JSON, and pass the whole thing at once.

 

So, my previous method was for my button to pass in the values for the Strings 'recordType', 'entity', 'job', 'item', 'quantity', 'amount, and just build the JSON Body by hand since the field names needed to be set:

 

HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();

//set my headers & endpoint, deleted for this board post

req.setBody('{"recordtype":"'+recordType+'", "entity":"'+entity+'", "job":"'+job+'","item":[{"item":"'+item+'", "quantity":"'+quantity+'", "amount":"'+amount+'"}]}');

res = http.send(req);

 

Notice the nested "item":[{item/quantity/amount}] area?  Well, I have multiple "item" sections -- one per child record -- that I need to get in this JSON.  The Parent has the recordtype, entity, and job.  So ideally I could, in the class, query for the child records and produce a new JSON body that ends up with multiple item sets like this:

 

req.setBody('{"recordtype":"'+recordType+'", "entity":"'+entity+'", "job":"'+job+'","item":[
{"item":"'+item[1]+'", "quantity":"'+quantity[1]+'", "amount":"'+amount[1]+'"},
{"item":"'+item[2]+'", "quantity":"'+quantity[2]+'", "amount":"'+amount[2]+'"},
{"item":"'+item[n..]+'", "quantity":"'+quantity[n..]+'", "amount":"'+amount[n..]+'"},
]}');

 

I figured the existing JSON methods would be helpful, but I can't figure out how to use 'em.  If anyone has already done this, I'd love to see the code you used to build this type of JSON.  If you wanted to help out using my situation you can assume my Child__c object's fields are just item__c, quantity__c, and amount__c, as in my query would be

 

//having passed the string "id" into the class from my Button on the parent object

list<Child__c> lineitems = [Select amount__c, quantity__c, item__c from Child__c WHERE Parent__c = :id];

 

My best guess at building the new JSON is pretty terrible so far so I won't paste that in just yet!

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

You definitely shouldn't be building by hand.

 

JSON is dead simple in Apex Code, and here's how.

 

First, you need some helper classes (they can be inner classes inside the class that holds your function):

 

public class ParentRecord {
    public String recordType, entity, job;
    public ChildRecord[] item;
    public ParentRecord(String recordType, String entity, String job) {
        this.recordType = recordType;
        this.entity = entity;
        this.job = job;
        item = new ChildRecord[0];
    }
}

public class ChildRecord {
    public String item;
    public Decimal quantity, amount;
    public ChildRecord(String item, Decimal quantity, Decimal amount) {
        this.item = item;
        this.quantity = quantity;
        this.amount = amount;
    }
}

Then, you build your Data&colon;

 

// Query parent and children, you can do both at once.
// Replace object names, relationship names, and field names.
Parent record = [SELECT Id, recordType, entity, job, (SELECT Id, Item, quantity, amount FROM Children) FROM Parent WHERE Id = :someId];

// Create a parent record entry from the utility class
ParentRecord parent = new ParentRecord(record.recordType, record.Entity, record.job);
// Loop through and build the item list
for(Child lineItem: record.Children) {
    parent.item.add(new ChildRecord(lineItem.Item, lineItem.quantity, lineItem.Amount));
}

 Now, at this point, you have just one task left: Converting the data to JSON. This is where the utility classes come in handy. Since all the data is now neatly laid out, we simply do this:

 

String jsonPayload = JSON.serialize(parent);

This takes care of all the little details for you. Quotes are escaped, numbers are properly formatted, nulls are defined correctly, and braces, brackets, commas, and colons all find their way to the right place with no effort on your part.

 

Finally, send the payload off to the remote server, and you're done.

 

 

 

All Answers

sfdcfoxsfdcfox

You definitely shouldn't be building by hand.

 

JSON is dead simple in Apex Code, and here's how.

 

First, you need some helper classes (they can be inner classes inside the class that holds your function):

 

public class ParentRecord {
    public String recordType, entity, job;
    public ChildRecord[] item;
    public ParentRecord(String recordType, String entity, String job) {
        this.recordType = recordType;
        this.entity = entity;
        this.job = job;
        item = new ChildRecord[0];
    }
}

public class ChildRecord {
    public String item;
    public Decimal quantity, amount;
    public ChildRecord(String item, Decimal quantity, Decimal amount) {
        this.item = item;
        this.quantity = quantity;
        this.amount = amount;
    }
}

Then, you build your Data&colon;

 

// Query parent and children, you can do both at once.
// Replace object names, relationship names, and field names.
Parent record = [SELECT Id, recordType, entity, job, (SELECT Id, Item, quantity, amount FROM Children) FROM Parent WHERE Id = :someId];

// Create a parent record entry from the utility class
ParentRecord parent = new ParentRecord(record.recordType, record.Entity, record.job);
// Loop through and build the item list
for(Child lineItem: record.Children) {
    parent.item.add(new ChildRecord(lineItem.Item, lineItem.quantity, lineItem.Amount));
}

 Now, at this point, you have just one task left: Converting the data to JSON. This is where the utility classes come in handy. Since all the data is now neatly laid out, we simply do this:

 

String jsonPayload = JSON.serialize(parent);

This takes care of all the little details for you. Quotes are escaped, numbers are properly formatted, nulls are defined correctly, and braces, brackets, commas, and colons all find their way to the right place with no effort on your part.

 

Finally, send the payload off to the remote server, and you're done.

 

 

 

This was selected as the best answer
ekorzekorz

sfdcfox strikes again!

 

Thanks, that did make it pretty easy, though "dead simple" for you is still like 2 hours of fiddling for me.  In any case, that was pretty much perfect.  My receiving endpoint wants all strings so I made the ChildRecord class ask for three strings instead.  

 

Also, I couldn't get this part to work exactly as typed, I think instead of parent.Children you mean to reference the variable "record", and instead of parent.line.add you meant parent.item.add.  

 

// Loop through and build the item list
for(Child lineItem: parent.Children) {
    parent.line.add(new ChildRecord(lineItem.Item, lineItem.quantity, lineItem.Amount));
}

 

so here are my edits that seem to get it to work.  

 

 

 // Loop through and build the item list
        for(Child lineItem: record.Children) {
            parent.item.add(new ChildRecord(lineItem.Item, lineItem.quantity, lineItem.amount));

 

Was that what you meant?  Or maybe I just misunderstood your or something.  


Anyway, you rock.  Thanks a ton!

sfdcfoxsfdcfox

No, your edits are just fine. I just missed that little bit of code, and you caught it just fine, so you're on your way. Glad I could help you out. Updated the solution with those two changes for future visitors.