Generate a clean JSON from a wrapper class for REST API

apexcommunityjavascriptsalesforcedxvisualforce

I am trying to create a JSON for outside REST API..
My code looks like –>

public class FordAccountAPI{
    public static void SendAccountInfo(list<id> fordaccId) {
        List<FORDAccountAPIWrapper> SendFordAccountAPI = new List<FORDAccountAPIWrapper>();
        
        list<account> acc = [Select Id,Building_Experience__c,Favourite_Feature__c,Non_negotiable_items__c,Primary_Client_s_Preferred_Hot_Drink__c,Secondary_Client_s_Preferred_Hot_Drink__c,Primary_Client_s_Preferred_Cold_Drink__c,Secondary_Client_s_Preferred_Cold_Drink__c,Primary_Client_s_Preferred_Drink__c,Secondary_Client_s_Preferred_Drink__c,Primary_Client_s_Diet_Preference__c,Secondary_Client_s_Diet_Preference__c,Primary_Client_s_Design_Taste__c,Secondary_Client_s_Design_Taste__c,Main_Contact__c,Communication_Frequency__c,Preferred_Communication_Time__c,Preferred_Communication_Mode__c,No_Communication__c,(select Id,Details__c from Family__r),(select Id,Details__c from Occupation__r),(select Id,Details__c from Recreation__r),(select Id,Details__c from Dream__r),(select Id,Details__c from Support_Journey__r),(select Id,Date__c,Details__c from Important_Dates__r),(select Id,Interior_Designer_Notes__c,SC_Design_Ideas__c from WOS_Ideas__r) from Account where id in : fordaccId];
                
        for (Account tempAcc : acc){
            FORDAccountAPIWrapper wrapperinner = new FORDAccountAPIWrapper();
            
            wrapperinner.AccountId  = tempAcc.Id;
            wrapperinner.Building_Experience = (tempAcc.Building_Experience__c  != null) ? tempAcc.Building_Experience__c  : '';
            wrapperinner.Favourite_Feature = (tempAcc.Favourite_Feature__c  != null) ? tempAcc.Favourite_Feature__c  : '';
            wrapperinner.Non_negotiable_items = (tempAcc.Non_negotiable_items__c  != null) ? tempAcc.Non_negotiable_items__c  : '';
            wrapperinner.Primary_Client_s_Preferred_Hot_Drink = (tempAcc.Primary_Client_s_Preferred_Hot_Drink__c  != null) ? tempAcc.Primary_Client_s_Preferred_Hot_Drink__c  : '';
            wrapperinner.Secondary_Client_s_Preferred_Hot_Drink = (tempAcc.Secondary_Client_s_Preferred_Hot_Drink__c  != null) ? tempAcc.Secondary_Client_s_Preferred_Hot_Drink__c  : '';
            wrapperinner.Primary_Client_s_Preferred_Cold_Drink = (tempAcc.Primary_Client_s_Preferred_Cold_Drink__c  != null) ? tempAcc.Primary_Client_s_Preferred_Cold_Drink__c  : '';
            wrapperinner.Secondary_Client_s_Preferred_Cold_Drink = (tempAcc.Secondary_Client_s_Preferred_Cold_Drink__c  != null) ? tempAcc.Secondary_Client_s_Preferred_Cold_Drink__c  : '';
            wrapperinner.Primary_Client_s_Preferred_Drink = (tempAcc.Primary_Client_s_Preferred_Drink__c  != null) ? tempAcc.Primary_Client_s_Preferred_Drink__c  : '';
            wrapperinner.Secondary_Client_s_Preferred_Drink = (tempAcc.Secondary_Client_s_Preferred_Drink__c  != null) ? tempAcc.Secondary_Client_s_Preferred_Drink__c  : '';
            wrapperinner.Primary_Client_s_Diet_Preference = (tempAcc.Primary_Client_s_Diet_Preference__c  != null) ? tempAcc.Primary_Client_s_Diet_Preference__c  : '';
            wrapperinner.Secondary_Client_s_Diet_Preference = (tempAcc.Secondary_Client_s_Diet_Preference__c  != null) ? tempAcc.Secondary_Client_s_Diet_Preference__c  : '';
            wrapperinner.Primary_Client_s_Design_Taste = (tempAcc.Primary_Client_s_Design_Taste__c  != null) ? tempAcc.Primary_Client_s_Design_Taste__c  : '';
            wrapperinner.Secondary_Client_s_Design_Taste = (tempAcc.Secondary_Client_s_Design_Taste__c  != null) ? tempAcc.Secondary_Client_s_Design_Taste__c  : '';
            wrapperinner.Main_Contact = (tempAcc.Main_Contact__c  != null) ? tempAcc.Main_Contact__c  : '';
            wrapperinner.Communication_Frequency = (tempAcc.Communication_Frequency__c  != null) ? tempAcc.Communication_Frequency__c  : '';
            wrapperinner.Preferred_Communication_Time = (tempAcc.Preferred_Communication_Time__c  != null) ? tempAcc.Preferred_Communication_Time__c  : '';
            wrapperinner.Preferred_Communication_Mode = (tempAcc.Preferred_Communication_Mode__c  != null) ? tempAcc.Preferred_Communication_Mode__c  : '';
            wrapperinner.No_Communication = (tempAcc.No_Communication__c  != null) ? tempAcc.No_Communication__c  : '';
            
            for(Family__c fm : tempAcc.Family__r){
                Family__c fp = new Family__c();
                fp.Id = (fm.Id != null ? fm.Id : '');   
                fp.Details__c = (fm.Details__c != null ? fm.Details__c : '');
                wrapperinner.Family.add(fp);
            }
            
            for(Occupation__c oc : tempAcc.Occupation__r){
                Occupation__c op = new Occupation__c();
                op.Id = (oc.Id != null ? oc.Id : '');   
                op.Details__c = (oc.Details__c != null ? oc.Details__c : '');
                wrapperinner.Occupation.add(op);
            }
            
            for(Recreation__c rc : tempAcc.Recreation__r){
                Recreation__c rp = new Recreation__c();
                rp.Id = (rc.Id != null ? rc.Id : '');   
                rp.Details__c = (rc.Details__c != null ? rc.Details__c : '');
                wrapperinner.Recreation.add(rp);
            }
            
            for(Dream__c dr : tempAcc.Dream__r){
                Dream__c dp = new Dream__c();
                dp.Id = (dr.Id != null ? dr.Id : '');   
                dp.Details__c = (dr.Details__c != null ? dr.Details__c : '');
                wrapperinner.Dream.add(dp);
            }
            
            for(Support_Journey__c sj : tempAcc.Support_Journey__r){
                Support_Journey__c sp = new Support_Journey__c();
                sp.Id = (sj.Id != null ? sj.Id : '');   
                sp.Details__c = (sj.Details__c != null ? sj.Details__c : '');
                wrapperinner.SupportJourney.add(sp);
            }
            
            for(Important_Date__c im : tempAcc.Important_Dates__r){
                Important_Date__c ip = new Important_Date__c();
                ip.Id = (im.Id != null ? im.Id : '');
                ip.Date__c = im.Date__c;        
                ip.Details__c = (im.Details__c != null ? im.Details__c : '');
                wrapperinner.ImportantDate.add(ip);
            }
            
            for(WOS_Idea__c wi : tempAcc.WOS_Ideas__r){
                WOS_Idea__c wp = new WOS_Idea__c();
                wp.Id = (wi.Id != null ? wi.Id : '');
                wp.Interior_Designer_Notes__c = (wi.Interior_Designer_Notes__c != null ? wi.Interior_Designer_Notes__c : '');
                wp.SC_Design_Ideas__c = (wi.SC_Design_Ideas__c != null ? wi.SC_Design_Ideas__c : '');
                wrapperinner.WOSIdeas.add(wp);
            }
            
            SendFordAccountAPI.add(wrapperinner);
        }
        
        system.debug('list of account change is'+SendFordAccountAPI);
        system.debug('checking the log injson>>>>'+JSON.serialize(SendFordAccountAPI));
        String jsonString = JSON.serialize(SendFordAccountAPI);
        system.debug('JSON@@: '+jsonString);
        If(!SendFordAccountAPI.isempty() && !Test.isRunningTest()) 
        {
            FordAccountChangeAPI(jsonString);
            //system.debug('I am sending@@');
        }
        
    }
    
    @Future(callout=true)
    public static void FordAccountChangeAPI(string JSONData) 
    {
        EndPoint_Utility.EndPointWrapper SendAccountInfoEndPoint = new EndPoint_Utility.EndPointWrapper();
        SendAccountInfoEndPoint = EndPoint_Utility.SendAccountInfo();
        HttpRequest req = new HttpRequest();
        req.setMethod('POST');
        req.setHeader('Content-type','Application/json');
        req.setHeader('Client_id',SendAccountInfoEndPoint.Client_id);
        req.setHeader('Client_secret',SendAccountInfoEndPoint.Client_secret);
        req.setEndpoint(SendAccountInfoEndPoint.EndPoint);
        
        req.setBody(JSONData); 
        
        Http http = new Http();
        HTTPResponse res = http.send(req);
        Map<String, Object> authresponse = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
        string message = String.valueOf(authresponse.get('RETURN'));
        //system.debug('message@@'+message);
    }
    
    public class FORDAccountAPIWrapper{
        public String AccountId;
        public String Building_Experience;
        public String Favourite_Feature;
        public String Non_negotiable_items;
        public String Primary_Client_s_Preferred_Hot_Drink;
        public String Secondary_Client_s_Preferred_Hot_Drink;
        public String Primary_Client_s_Preferred_Cold_Drink;
        public String Secondary_Client_s_Preferred_Cold_Drink;
        public String Primary_Client_s_Preferred_Drink;
        public String Secondary_Client_s_Preferred_Drink;
        public String Primary_Client_s_Diet_Preference;
        public String Secondary_Client_s_Diet_Preference;
        public String Primary_Client_s_Design_Taste;
        public String Secondary_Client_s_Design_Taste;
        public String Main_Contact;
        public String Communication_Frequency;
        public String Preferred_Communication_Time;
        public String Preferred_Communication_Mode;
        public String No_Communication;
        public List<Family__c> Family;
        public List<Occupation__c> Occupation;
        public List<Recreation__c> Recreation;
        public List<Dream__c> Dream;
        public List<Support_Journey__c> SupportJourney;
        public List<Important_Date__c> ImportantDate;
        public List<WOS_Idea__c> WOSIdeas;
        
        public FORDAccountAPIWrapper(){
            AccountId = '';
            Building_Experience = '';
            Favourite_Feature = '';
            Non_negotiable_items = '';
            Primary_Client_s_Preferred_Hot_Drink = '';
            Secondary_Client_s_Preferred_Hot_Drink = '';
            Primary_Client_s_Preferred_Cold_Drink = '';
            Secondary_Client_s_Preferred_Cold_Drink = '';
            Primary_Client_s_Preferred_Drink = '';
            Secondary_Client_s_Preferred_Drink = '';
            Primary_Client_s_Diet_Preference = '';
            Secondary_Client_s_Diet_Preference = '';
            Primary_Client_s_Design_Taste = '';
            Secondary_Client_s_Design_Taste = '';
            Main_Contact = '';
            Communication_Frequency = '';
            Preferred_Communication_Time = '';
            Preferred_Communication_Mode = '';
            No_Communication = '';
            Family = new List<Family__c>();
            Occupation = new List<Occupation__c>();
            Recreation = new List<Recreation__c>();
            Dream = new List<Dream__c>();
            SupportJourney = new List<Support_Journey__c>();
            ImportantDate = new List<Important_Date__c>();
            WOSIdeas = new List<WOS_Idea__c>();
          }
        
    }
}

Its working fine but generated JSON is not clean. When I am checking the debug of JSON.serialize(SendFordAccountAPI) it looks like having lots of unwanted parameters –>

[
   {
      "WOSIdeas":[
         {
            "attributes":{
               "type":"WOS_Idea__c",
               "url":"/services/data/v52.0/sobjects/WOS_Idea__c/a1Q0w000000RGdBEAW"
            },
            "Id":"a1Q0w000000RGdBEAW",
            "Interior_Designer_Notes__c":"He has selected all grange range doors for his new build.",
            "SC_Design_Ideas__c":"He is happy with grange and want grange range toilet fittings."
         },
         {
            "attributes":{
               "type":"WOS_Idea__c",
               "url":"/services/data/v52.0/sobjects/WOS_Idea__c/a1Q0w000000RGd1EAG"
            },
            "Id":"a1Q0w000000RGd1EAG",
            "Interior_Designer_Notes__c":"He has selected all grange range doors for his new build.",
            "SC_Design_Ideas__c":"He is happy with grange and want grange range toilet fittings."
         }
      ],
      "SupportJourney":[
         {
            "attributes":{
               "type":"Support_Journey__c",
               "url":"/services/data/v52.0/sobjects/Support_Journey__c/a1P0w000000CjOsEAK"
            },
            "Id":"a1P0w000000CjOsEAK",
            "Details__c":"He is worried with all the build steps."
         }
   }
]

I just want to have a clean JSON to sent to other system and should look like this –> (basically remove unwanted 'attribute' paramter and sub parameter 'type', 'url' from it)

[
   {
      "WOSIdeas":[
         {
            "Id":"a1Q0w000000RGdBEAW",
            "Interior_Designer_Notes__c":"He has selected all grange range doors for his new build.",
            "SC_Design_Ideas__c":"He is happy with grange and want grange range toilet fittings."
         },
         {
            "Id":"a1Q0w000000RGd1EAG",
            "Interior_Designer_Notes__c":"He has selected all grange range doors for his new build.",
            "SC_Design_Ideas__c":"He is happy with grange and want grange range toilet fittings."
         }
      ],
      "SupportJourney":[
         {
            "Id":"a1P0w000000CjOsEAK",
            "Details__c":"He is worried with all the build steps."
         }
   }
]

I have tried a couple of solutions from web but nothing is working.

Best Answer

To avoid this "dirty" JSON, you need to stop using SObjects in your wrapper class entirely.

An SObject can provide you access to a Map, using SObject.getPopulatedFieldsAsMap. If you replace your SObjects in the wrapper with Map<String, Object> and populate these maps with the result of calling get populated fields as map you should get the output you want.

For example, change Family from (what I assume is) List<SObject> to be List<Map<String, Object>> instead then update:

for (Family__c fm : tempAcc.Family__r){
    Family__c fp = new Family__c();
    fp.Id = (fm.Id != null ? fm.Id : '');   
    fp.Details__c = (fm.Details__c != null ? fm.Details__c : '');
    wrapperinner.Family.add(fp);
}

to:

for (Family__c fm : tempAcc.Family__r) {
    Family__c fp = new Family__c();
    fp.Id = (fm.Id != null ? fm.Id : '');   
    fp.Details__c = (fm.Details__c != null ? fm.Details__c : '');
    wrapperinner.Family.add(fp.getPopulatedFieldsAsMap());
}

Change all other cases in a similar way. NB: I have assumed that you don't have populated fields here that are themselves SObject records.