[SalesForce] How to create JSON string for REST callout from Wrapper class

I have found a lot of different examples of this, but I'm still having troubles accomplishing this. Here is the webservice which is working:

//WORKING Webservice in target org

@RestResource(urlMapping='/v1/workwebservice/*')
global with sharing class REST_WorkService_V1 {

@HttpPost
global static PostResponseWrapper doPost(RequestWrapper rqst) {
    RestRequest req = RestContext.request;
    RestResponse res = RestContext.response;
    PostResponseWrapper response = new PostResponseWrapper();
    System.debug('**response : ' + response); 

    try {

        insert rqst.workList;
        response.workList = rqst.workList;

        response.status = 'Success';
        response.message = 'Your Work records have been created successfully';
    }
    catch(Exception exc) {
        res.StatusCode = 500;
        response.workList = null;
        response.status = 'Error';
        response.message = 'Sorry, your request failed with the following error: ' + exc.getMessage();
    }

    return response;
}

global class RequestWrapper {
    List<Work__c> workList;
}

global class PostResponseWrapper {
    List<Work__c> workList;
    String status;
    String message;

    public PostResponseWrapper(){

    }
}   
}

Here is the sample JSON request that will work :

//WORKING JSON request body string
{
  "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
      }
    ]
  }
}

However, I am having a problem knowing how to create this JSON string from data in my org within a custom Work__c object. I want to serialize the data so that it exactly matches the above sample request.

This code exists inside a batch class that is going to periodically pass records from one Salesforce org to another . So, I have a list of Work__c records that need to be serialized into above JSON format and passed in a callout.

// I am passing in the List<Work__c> into my method

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

// If I directly serialize the Work__c list:

String jsonSer = JSON.serialize(scopeList);
            System.debug(jsonSer);

// Here is the prettified JSON request : 

[
  {
    "attributes": {
      "type": "Work__c",
      "url": "/services/data/v44.0/sobjects/Work__c/a390H00000211xcQAA"
    },
    "Id": "a390H00000211xcQAA",
    "Due_Formula__c": -2,
    "DueDate__c": "2019-01-02",
    "Name": "Feature - at end of sprint, batch should roll over all those that are not comple"
  },
  {
    "attributes": {
      "type": "Work__c",
      "url": "/services/data/v44.0/sobjects/Work__c/a390H00000211xhQAA"
    },
    "Id": "a390H00000211xhQAA",
    "Due_Formula__c": -2,
    "DueDate__c": "2019-01-02",
    "Name": "Enable Field History tracking for Sprint"
  }
]

So, I am wanting to use a Wrapper class to send "rqst" as the outer-most JSON level from my Work__c custom object.

//
// Generated by JSON2Apex http://json2apex.herokuapp.com/
//

//NOT WORKING

public class WorkRequest {

public Rqst rqst;

public class WorkList {
    public String Name {get;set;}
    public String Sprint {get;set;}//Sprint__c;
    public String Description {get;set;}//Description__c;
    public Boolean isTest {get;set;}//isTest__c;

    public WorkList(String n, String spr, String des, Boolean t) {
        Name = n;
        Sprint = spr;
        Description = des;
        isTest = t;
    }
}

public class Rqst {
    public List<WorkList> workList;

    public Rqst() {
        this.workList = workList;
    }
}

public WorkRequest() {
        this.rqst = Rqst;
    }   
}

I am not understanding how the "Sprint__c" will be assigned from the parameter for "Sprint" ( I can't save it with __c : "Invalid character in identifier: Sprint__c (Line: 11, Column: 17). I also do not understand how to add my specific "Work__c" records to — public List workList

Thanks in advance for your help. This is a simple problem that I do not know how to solve, but hopefully it can help others if you can look at my specific code and suggest how to fix it.

Sources :

Best Answer

You can do the following workaround to make this happen. First, generate the wrapper class from the JSON (it will have those __c). Then replace the __c to _c to Save the wrapper class (WorkRequest).

Now you can populate the data in the wrapper class, Serialize it, get the raw JSON String and replace all the _c to __c before sending to the request as below. By doing this you can send the JSON as required by your web service.

String rqString = System.JSON.serialize(wr);
System.debug(rqString);
rqString = rqString.replaceAll('_c', '__c');
System.debug(rqString);

Wrapper Class

//
// Generated by JSON2Apex http://json2apex.herokuapp.com/
//

public class WorkRequest {

    public Rqst rqst;

    public class WorkList {
        public String Name;
        public String Sprint_c;
        public String Description_c;
        public Integer isTest_c;
    }

    public class Rqst {
        public List<WorkList> workList;
    }


    public static WorkRequest parse(String json) {
        return (WorkRequest) System.JSON.deserialize(json, WorkRequest.class);
    }
}