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
dlattedlatte 

Simplified example with Ping to demonstrate behavior I am trying to resolve. ****Malformed JSON: Expected '{' at the beginning of object

//Test HttpPOST ping method
    static testMethod void postPingTest1() {
        RestRequest req = new RestRequest();
        RestResponse res = new RestResponse();
        String postData = '{"email":"ping"}';

        String JsonMsg=JSON.serialize(postData);
        System.debug('Serialized Json ' + JsonMsg);
        req.requestBody = Blob.valueOf(JsonMsg);

        req.requestURI = '/services/apexrest/gdpr/v1/GDPRContactMask/';
        req.httpMethod = 'POST';
        RestContext.request = req;
        RestContext.response = res;

        Test.startTest();
        GDPRContactMaskWSv1.maskDetails();
        Test.stopTest();

        System.assertEquals(201, RestContext.response.statusCode);
        Map<String, Object> m = (Map<String, Object>) JSON.deserializeUntyped(RestContext.response.responseBody.toString());
        System.assertEquals('Working', m.get('message'));
    }
Below I am just displaying the logic from the @RestResource(urlMapping='/gdpr/v1/GDPRContactMask/*') global with sharing class GDPRContactMaskWSv1 { that pertains to the @HttpPost method I am testing.   
@HttpPost
    global static void maskDetails() {

        String strJson;
        String responseMsg;
        String email;

        Logger.push('gdprContactMask', 'GDPRContactMaskWSv1');

        RestContext.response.addHeader('Content-Type', 'application/json');
        RestRequest request = RestContext.request;

        strJson = System.RestContext.request.requestBody.toString();
        System.debug('restBody ' + strJson);

        try {
            // deserialize the maskGDPRData from the JSON string.
            GDPRDataWrapper maskGDPRData = GDPRDataWrapper.getParsedMaskDataJson(strJson);
            System.debug('maskDetails after deserialized');
            if (maskGDPRData != null) {

                email = maskGDPRData.email;

                // Valid email is required data
                if (String.isBlank(email)) {
                    RestContext.response.statuscode = 400;
                    RestContext.response.responseBody = Blob.valueOf('{ "errorCode" : "400", "message" : "' + System.Label.GDPR_ContactMaskRequiredFields + '" }');
                    Logger.pop();
                    return;
                }

                if (String.isNotBlank(email)) {
                    System.debug('GDPR Email ' + email);

                    // Ping request
                    if (email.toLowerCase() == 'ping') {
                        System.debug('In POST Ping');
                        processPing();
                        Logger.pop();
                        return;
                    } else { // mask Request

                        GDPR_UtilityHelper utilityHelper = new GDPR_UtilityHelper();
                        responseMsg = utilityHelper.GDPRUtilityHelper(maskGDPRData);
                    }
                }

                // Grab the responseMsg and send back to consumer

                if (String.isNotBlank(responseMsg)) {
                    RestContext.response.statuscode = 500;
                    RestContext.response.responseBody = Blob.valueOf(responseMsg);
                } else {
                    RestContext.response.statuscode = 201;
                    RestContext.response.responseBody = Blob.valueOf(strJson); // including original strJson but may change to just return Success
                }
            }
        } catch (DmlException dmlEx) {
            Logger.debugException(dmlEx.getMessage());
            system.debug('****Exception in GDPR Contact Mask****' + dmlEx.getMessage());
            strJson = 'Failure:' + (dmlEx.getMessage().replace('GDPR Mask Contact Update failed.,', '')).replace(': []', '');
            RestContext.response.statuscode = 400;
            RestContext.response.responseBody = Blob.valueOf('{ "errorCode" : "400", "message" : "' + strJson + '" }');

        } catch (Exception ex) {
            Logger.debugException(ex.getMessage());
            system.debug('****Exception in GDPR Contact Mask:****' + ex.getMessage());
            strJson = 'Failure:' + ex.getMessage();
            RestContext.response.statuscode = 400;
            RestContext.response.responseBody = Blob.valueOf('{ "errorCode" : "400", "message" : "' + strJson + '" }');
        }
Output from my log showing the JSON has the '{' at the beginning. 
18:14:18.2 (7452161)|USER_DEBUG|[160]|DEBUG|Serialized Json "{\"email\":\"ping\"}"
18:14:18.2 (45303165)|USER_DEBUG|[34]|DEBUG|restBody "{\"email\":\"ping\"}"
18:14:18.2 (47385844)|USER_DEBUG|[30]|DEBUG|In GDPRDataWrapper parse Json "{\"email\":\"ping\"}"
18:14:18.2 (52017541)|USER_DEBUG|[87]|DEBUG|****Exception in GDPR Contact Mask:****Malformed JSON: Expected '{' at the beginning of object
/**
 * Created by dlatte on 10/9/2018.
 */

public class GDPRDataWrapper {

    public String email { get; set; }
    public String maskedEmail { get; set; }
    public String firstName { get; set; }
    public String middleName { get; set; }
    public String lastName { get; set; }
    public String firstNameLatin { get; set; }
    public String lastNameLatin { get; set; }
    public String mailingStreet { get; set; }
    public String mailingCity { get; set; }
    public String mailingPostalCode { get; set; }
    public String latinStreet { get; set; }
    public String latinCity { get; set; }
    public String workPhone { get; set; }
    public String fax { get; set; }
    public String mobilePhone { get; set; }
    public String homePhone { get; set; }
    public String otherPhone { get; set; }
    public String contactStatus { get; set; }


// parse JSon Method
    public static GDPRDataWrapper getParsedMaskDataJson(String jsonToParse) {

        System.debug('In GDPRDataWrapper parse Json ' + jsonToParse);
        return (GDPRDataWrapper) JSON.deserialize(jsonToParse, GDPRDataWrapper.class);
    }
}

The above logic works when I run my Postman collection.
My test is where I'm having the issue with the Malformed JSON, even though the JSON request is exactly like my postman Body..
 
{  
    "email": "cc@gmail.com.mwtest",
    "maskedEmail": "unique2MaskedEmail@test.com",
    "firstName": "Delete",
    "middleName": "Delete",
    "lastName": "Delete",
    "firstNameLatin": "",
    "lastNameLatin": "",
    "mailingStreet": "Delete",
    "mailingCity": "Delete",
    "mailingPostalCode": "000000",
    "latinStreet": "",
    "latinCity": "Delete",
    "workPhone": "",
    "fax": "Delete",
    "mobilePhone": "Delete",
    "homePhone": "Delete",
    "otherPhone": "",
    "contactStatus": "Junk"
}

 
SandhyaSandhya (Salesforce Developers) 
Hi,

You may try the solution from below link which uses wrapper class.

https://salesforce.stackexchange.com/questions/222136/deserialize-json-string-to-custom-apex-class
 
Best Regards,
Sandhya