4

I resolved this issue my changing res.setBody('123') as json thanks to all I am trying to deserialize as follows:

webservice static void RESTApiToAccount(id AccountId)
{
    String clientId = 'XXXX';
    String clientSecret = 'XXX';
    String username = 'XXX';
    String password = 'XXXX';
    String reqbody = 'grant_type=password&client_id='+clientId+'&client_secret='+clientSecret+'&username='+username+'&password='+password;
    Http h = new Http();
    HttpRequest req = new HttpRequest();
    req.setBody(reqbody);
    req.setMethod('POST');
    req.setEndpoint('https://ap4.salesforce.com/services/oauth2/token');
    HttpResponse res = h.send(req);
    SendAccountUsingRESTAPI resp1 = (SendAccountUsingRESTAPI)JSON.deserialize(res.getbody(),SendAccountUsingRESTAPI.class);

    String accessToken;
    accessToken = resp1.access_token;
    if(accessToken != null)
    {
    String endPoint = 'https://ap4.salesforce.com/services/apexrest/Account';
    JSONGenerator gen = JSON.createGenerator(true);
    Account a=[select id,name,website from account where id=:AccountId];
    gen.writeStartObject();
    gen.writeStringField('name', a.name);
    gen.writeStringField('id', a.id);
    gen.writeStringField('website', a.website);
    String s=gen.getasString();
    Http h2 = new Http();
    HttpRequest req1 = new HttpRequest();
    req1.setHeader('Authorization','Bearer ' + accessToken);
    req1.setHeader('Content-Type','application/json');
    req1.setHeader('accept','application/json');
    req1.setBody(s);

    req1.setMethod('POST');
    req1.setEndpoint(endPoint);
    HttpResponse res1 = h2.send(req1);
    String trimmedResponse = res1.getBody();
    system.debug('sasasasa'+res1);
    system.debug('@@@RESPONSE@@'+trimmedResponse);
    JSONParser parser = JSON.createParser(res1.getBody());
}

I am getting this error when trying to use a mock call:

Malformed JSON: Expected '{' at the beginning of object

What should I be doing to deserialize my data?

@isTest
static void myTest() { // Set mock callout class 
    Test.startTest();

    Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());

    Account a=new account();
    a.name='test';
    a.website='www.test.com';

    SendAccountUsingRESTAPI.RESTApiToAccount(a.id);

    Test.StopTest();
}

MockHttpResponseGenerator class:

@isTest
public class MockHttpResponseGenerator implements HttpCalloutMock {
    // Implement this interface method
    public HTTPResponse respond(HTTPRequest req) {
             String endpoint = req.getEndpoint();
        if ( endpoint.contains('oauth2/token') ) {
            return buildOAuthResponse( req );
        } else if ( endpoint.contains('/services/apexrest/Account') ) {
            return buildShortenResponse( req );
        }
        return null;
    }
  private HttpResponse buildOAuthResponse( HttpRequest req ) {
        HttpResponse res = new HttpResponse();
        res.setBody('123');
        res.setStatusCode(200);
        return res;
    }
    private HttpResponse buildShortenResponse( HttpRequest req ) {

        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"foo":"bar"}');       
        res.setStatusCode(200);
        return res;
    } 
}
  • 2
    problem is that during res.setBody('123'); proper json is not being returned – kurunve Jan 11 '17 at 14:29
  • Yup, just as kurunve said, if you debug res.getBody() you'll see that the json is malformed. Instead of generating the response dynamically you can store it as a static resource and call it that way... – Ross Bassett Jan 11 '17 at 14:32
  • If I set the body from res.setBody('123'); to res.setBody('{"foo":"bar"}'); it will pass but I can't get code coverage because access token will come null and will not enter the loop.Please find my updated question – Salesforce Learner Jan 11 '17 at 14:51
  • @SalesforceLearner Is there a reason why you're choosing not to use SingleRequestMock() or MultiRequestMock()? Testing Apex Callouts – akcorp2003 Jan 11 '17 at 15:37
4

Any time I test deserialization, I feed directly serialized data into the system as my input. It's much easier to control and understand, especially with complex structures.

MyClass.SendAccountUsingRESTAPI data = new MyClass.SendAccountUsingRESTAPI();
data.access_token = '<some_value>';
response.setBody(JSON.serialize(data));

You may also find that this out of the box serialization process is more succinct for other objects as well, such as the Account record you included in your OP.

Verbose

JSONGenerator gen = JSON.createGenerator(true);
Account a=[select id,name,website from account where id=:AccountId];
gen.writeStartObject();
gen.writeStringField('name', a.name);
gen.writeStringField('id', a.id);
gen.writeStringField('website', a.website);
String s=gen.getasString();

Succinct

String s = JSON.serialize([SELECT Id, Name, Website FROM Account WHERE Id = :AccountId]);
  • Ah, and I thought I was the only one that was weird that way... – sfdcfox Jan 12 '17 at 6:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.