[SalesForce] How to serialize REST Request from Wrapper class for existing Salesforce data

I am trying to format my SObject data within a wrapper class to POST data to another Salesforce org from a custom Work__c object, but I am having a hard time understanding how to add an instance of "cls_WorkList" to my array "workList" within "cls_rqst".

//
//Generated by AdminBooster
//

public class WorkRequest2{

public cls_rqst rqst;

public class cls_rqst {
    public cls_workList[] workList;
}

public class cls_workList {
    public String Name; //TestWorkItem
    public String Sprint_c; //a09f100000Hw0iM
    public String Description_c;    //This is a description
    public Boolean isTest_c;    //1
    public String Status_c;

    public cls_workList(String n, String spr, String des, Boolean t, ) {
        Name = n;
        Sprint_c = spr;
            Description_c = des;
            isTest_c = t;
        }
    }

    public WorkRequest2() {    
    }
}

UPDATED :

//
//Generated by AdminBooster
//

public class WorkRequest2{

    public requestOuter rqst {get;set;}

    public class requestOuter {
        public List<WorkListClass> WorkList {get;set;}    

        public requestOuter() {
            //this.WorkList = WorkList;
            //WorkListClass wlc = new WorkListClass(null,null,null,null);
        }

    }

    public class WorkListClass {
        public String Name {get;set;}
        public String Sprint_c {get;set;}
        public String Description_c {get;set;}
        public Boolean isTest_c {get;set;}

        public WorkListClass(String n, String spr, String des, Boolean t ) {
            Name = n;
            Sprint_c = spr;
            Description_c = des;
            isTest_c = t;
        }
    }

    public WorkRequest2() {
        //this.rqst = rqst;
        //requestOuter r = new RequestOuter();
    }

}

So, below you will see my very hack-ily getting around this by serializing WorkRequest2.cls_workList and then adding the necessary lines around it to be formatted correctly for my JSON request.

public void actualCallout(String inputString, List<Work__c> scopeList) {

        OAuth2 objAuthenticationInfo = (OAuth2)JSON.deserialize(inputString, OAuth2.class);

        Http h1 = new Http();
        HttpRequest req1 = new HttpRequest();
        req1.setHeader('Authorization','Bearer '+objAuthenticationInfo.access_token);
        req1.setHeader('Content-Type','application/json');
        req1.setHeader('accept','application/json');

        WorkRequest.Rqst workRequest = new WorkRequest.Rqst(); 

        /// HACKY HACKY HACKY
        String reqSTRINGINNER = '';
        Integer limitDebug = 0;

        for(Work__c w : scopeList) {
            limitDebug = limitDebug + 1;    
            System.debug('**limitDebug :' + limitDebug);
            if(limitDebug < scopeList.size() ) 
            {
                WorkRequest2.cls_worklist wlitem = new WorkRequest2.cls_workList(w.name, 'a09f100000Hw0iM', w.Description__c,  w.isTest__c);  
                String serializeExample = JSON.serialize(wlitem);
                reqSTRINGINNER = reqSTRINGINNER + serializeExample;
            }

            //HACKY HACKY HACKY
            //Need to figure out how to build this from apex and add to apex class
            if(limitDebug < scopeList.size() - 1 ) {
                system.debug('**add comma except for last comma');
                reqSTRINGINNER = reqSTRINGINNER + ',';
            }
        }

        String BEGSTRING = '{"rqst":{"workList":[';
        String ENDSTRING = ']}}';
        String almostFinalString = BEGSTRING + reqSTRINGINNER + ENDSTRING;
        String rqString = almostFinalString.replaceAll('_c', '__c');

        req1.setBody(rqString);           
        req1.setMethod('POST');
        req1.setendpoint('https://myorg-dev-ed.my.salesforce.com/services/myservice/v1/mywebservice/');

        HttpResponse res1 = h1.send(req1);

}

Given above hacky code which is working but is obviously not the smartest code, how can I do this the non-hacky and correct way by serializing my wrapper class "WorkRequest2"?

UPDATED AND WORKING :

public void actualCallout(String inputString, List<Work__c> scopeList) {

        OAuth2 objAuthenticationInfo = (OAuth2)JSON.deserialize(inputString, OAuth2.class);

        Http h1 = new Http();
        HttpRequest req1 = new HttpRequest();
        req1.setHeader('Authorization','Bearer '+objAuthenticationInfo.access_token);
        req1.setHeader('Content-Type','application/json');
        req1.setHeader('accept','application/json');

        WorkRequest2 wr2 = new WorkRequest2();
        wr2.rqst = new WorkRequest2.requestOuter();
        wr2.rqst.workList = new WorkRequest2.WorkListClass[0];

        for(Work__c w : scopeList) {
            wr2.rqst.workList.add(new WorkRequest2.WorkListClass(w.name, 'a09f100000Hw2vp', w.Description__c, w.isTest__c) );
        }

        String serializedData = JSON.serialize(wr2);
        System.debug('**serializedData : ' + serializedData);
        String rqString = serializedData.replaceAll('_c', '__c');

        //String sampleJSONString = '{"rqst":{"workList":[{"Name":"TestWorkItem","Sprint__c":"a09f100000Hw0iM","Description__c":"This is a description","isTest__c":1},{"Name":"TestWorkItem2","Sprint__c":"a09f100000Hw0iM","Description__c":"2nd description","isTest__c":1},{"Name":"TestWorkItem3","Sprint__c":"a09f100000Hw0iM","Description__c":"del 3 description","isTest__c":1}]}}';

        req1.setBody(rqString);//Send JSON body

        System.debug('**Request body ' + req1.getBody());
        req1.setMethod('POST');
        req1.setendpoint('https://nonce-dev-ed.my.salesforce.com/services/apexrest/v1/workwebservice/');

        HttpResponse res1 = h1.send(req1);
        system.debug('**RESPONSE_BODY'+res1.getbody());      


}

Best Answer

You should simply serialize an instance of WorkRequest2 with all of your child records included.

wr2 = new WorkRequest2();
wr2.rqst = new cls_rqst();
wr2.rqst.workList = new cls_workList[0];

wr2.rqst.workList.add(new cls_workList( ... DATA_HERE ... ));

You can clean this up considerably by implementing constructors for WorkRequest2 and cls_rqst that initialize their instance variables. Alternately, just create a constructor for WorkRequest2 that accepts a cls_workList[] and handles all the inner setup.

Whichever route you take, you end up with a data structure such that you can directly do

String serializedData = JSON.serialize(wr2);

It's not clear from the code you're using why you have cls_workList at all. It seems to just be a facade over an sObject, which requires you to jump through some additional hoops to get the data structure you need. Why not serialize the sObject itself, or just use a Map<String, Object>?