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
kezia dolakezia dola 

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

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

I am getting this error while running this API. This is my code:

public class QcAPI {
    @future(callout=true)
    public static void callServer(String id){
        Opportunity opp =[Select Id,Account.FirstName,Account.ShippingAddress,Account.BillingAddress, Account.LastName,Email__c,DUP_Mobile__c,account.BillingStreet,account.BillingCity,account.BillingState,account.BillingCountry,account.BillingPostalCode,
                          account.ShippingStreet,account.ShippingCity,account.ShippingState,account.ShippingCountry,account.ShippingPostalCode from Opportunity where id=: id limit 1];
        
        OpportunityDataWrap oppdata = new OpportunityDataWrap();
        String rno = opp.Account.LastName+'-'+opp.Id;
        oppdata.refno = rno;
        oppdata.syncOnly = true;
        oppdata.deliveryMode = 'API';
        
        if(opp.Account.ShippingAddress !=null){
            ShippingAddressWrap cc = new ShippingAddressWrap();
            cc.firstname = opp.Account.LastName;
            cc.lastname = '';
            cc.email = opp.Email__c;
            cc.telephone = '+91'+opp.DUP_Mobile__c;
            cc.country = 'IN';
            cc.line1 = opp.Account.ShippingStreet;
            cc.line2 = '-';
            cc.city = opp.Account.ShippingCity;
            cc.postcode = opp.Account.ShippingPostalCode;
            cc.region = opp.Account.ShippingState;
            cc.billToThis = true;
            oppdata.address = cc;
        }
        
        if(opp.Account.BillingAddress !=null){
            BillingAddressWrap cb = new BillingAddressWrap();
            cb.firstname = opp.Account.lastname;
            cb.lastname = '';
            cb.email = opp.Email__c;
            cb.telephone = '+91'+opp.DUP_Mobile__c;
            cb.country = 'IN';
            cb.line1 = opp.Account.ShippingStreet;
            cb.line2 = '-';
            cb.city = opp.Account.ShippingCity;
            cb.postcode = opp.Account.ShippingPostalCode;
            cb.region = opp.Account.ShippingState; 
            oppdata.billing = cb;
        }
        List<paymentwrap> pw = new List<paymentwrap>();
        paymentwrap pwr = new paymentwrap();
        pwr.code = 'xyz';
        pwr.amount = 0;
        pw.add(pwr);
        oppdata.payments = pw;
        
        List<productsWrap> prodwrap = new List<productsWrap>();
        productsWrap pdwr = new productsWrap();
        pdwr.sku = 'xyzABCDE000';  
        pdwr.price = 0;
        pdwr.qty = 1;
        pdwr.currency_x =356;
        pdwr.giftMessage ='';
        pdwr.theme ='';
        prodwrap.add(pdwr);
        oppdata.products = prodwrap;
        system.debug('OppData:'+oppdata);
        String jsbody = JSON.serialize(oppdata);
        String jsonBody = jsbody.replace('currency_x', 'currency');
        system.debug('JSON BODY : '+jsonBody);
        map<string,Object> result = (map<string,Object>)JSON.deserializeUntyped(jsonBody);
        system.debug('result '+result);
        string endresult = JSON.serialize(result);
        system.debug('endresult '+endresult);

        String customLabelValue = Label.QCAPI+'/orders';
        //signature calling
        
        XYZ__c    Qc = XYZ__c.getvalues('XYZ details');
        string secretKeyValue = Qc.Consumer_secret__c;
        string reqMethod = 'POST';
        string url = EncodingUtil.URLEncode(Label.QCAPI+'/10000028/resend','UTF-8');
        system.JSONParser requestData = JSON.createParser(jsonBody);
        string endpoint = reqMethod + '&' + url;
        system.debug('end point url '+endpoint);
        string signature;
        Blob hmacData = Crypto.generateMac('HmacSHA512', Blob.valueOf(endpoint), Blob.valueOf(secretKeyValue));
        signature = encodingUtil.convertToHex(hmacData);
        system.debug('signature '+signature);
        
        string BearerToken = QCoauth.BearerToken();
        HttpRequest request = new HttpRequest();
        request.setEndpoint(customLabelValue);
        request.setMethod('POST');
        request.setHeader('Content-Type', 'application/json');
        request.setHeader('Authorization',BearerToken);
        request.setHeader('Accept','*/*');
        request.setBody(jsonBody);
        Http http = new Http();
        HttpResponse response = http.send(request);
        system.debug('get response :'+response.getBody());
        system.debug('get response :'+response);
        ResponseData rd = (ResponseData)JSON.deserialize(response.getBody(), ResponseData.class);
        System.debug('Response Data :'+rd);
        
        Opportunity oppty = new Opportunity();
        oppty.Id = opp.id;
        oppty.ABC__c = rd.cards[0].cardNumber;
 //       oppty.Pin__c = rd.cards[0].cardPin;
        update oppty;

    }
    
    public class ShippingAddressWrap{
        public String firstname{get;set;}
        public String lastname{get;set;} 
        public String email{get;set;} 
        public String telephone{get;set;} 
        public String line1{get;set;} 
        public String line2{get;set;} 
        public String city{get;set;} 
        public String region{get;set;} 
        public String country{get;set;} 
        public String postcode{get;set;} 
        public boolean billToThis{get;set;} 
    }
    
    public class BillingAddressWrap{
        public String firstname{get;set;}
        public String lastname{get;set;} 
        public String email{get;set;} 
        public String telephone{get;set;} 
        public String line1{get;set;} 
        public String line2{get;set;} 
        public String city{get;set;} 
        public String region{get;set;} 
        public String country{get;set;} 
        public String postcode{get;set;} 
    }
    public class paymentwrap{
        public string code{get;set;}
        public double amount{get;set;}
    }
    public class productsWrap{
        public string sku{get;set;}
        public double price{get;set;}
        public integer qty{get;set;}
        public integer currency_x{get;set;}
        public string giftMessage{get;set;}
        public string theme{get;set;}
    }
    public class OpportunityDataWrap{    
        Public ShippingAddressWrap address{get;set;}
        Public BillingAddressWrap billing{get;set;}
        Public List<paymentwrap> payments{get;set;}
        public string refno{get;set;}
        public List<productsWrap> products{get;set;}
        public boolean syncOnly{get;set;}
        public String deliveryMode{get;set;} 
    }
    public class ResponseData {
        public string status;
        public List<cardwrap> cards;
    }
    public class cardwrap{
        public string cardNumber;
        public string cardPin;
    }
}

Any idea to resolve this issue?

Thanks,
Kezia
Ashish Singh SFDCAshish Singh SFDC
Hi Kezia,

Exactly at what line you're getting this error?

I assume you're getting this error at :
ResponseData rd = (ResponseData)JSON.deserialize(response.getBody(), ResponseData.class);


Since ResponseData is an Object and you might be getting List<Object> in response this could cause the issue. If you have the API response structure in the documentation then please ahead and review it and check if either outer element is [] or {}
system.debug('get response :'+response);
public class ResponseData {
        public string status;
        public List<cardwrap> cards;
}

You can post the error line and the response structure if you still need any help.

Thanks,
Ashish Singh.
kezia dolakezia dola
Hi Ashish Singh,

Error line: ResponseData rd = (ResponseData)JSON.deserialize(response.getBody(),ResponseData.class);

Response Structure: 
{
    "syncOnly": true,
    "refno": "Test woohoo-0065D000005l7ojQAA",
    "products": [
        {
            "theme": "",
            "sku": "xyzABCDE000",
            "qty": 1,
            "price": 0.0,
            "giftMessage": "",
            "currency": 356
        }
    ],
    "payments": [
        {
            "code": "xyz",
            "amount": 0.0
        }
    ],
    "deliveryMode": "API",
    "billing": {
        "telephone": "+916789876780",
        "region": "Karnataka",
        "postcode": "560037",
        "line2": "-",
        "line1": "567",
        "lastname": "",
        "firstname": "Test woohoo",
        "email": null,
        "country": "IN",
        "city": "Bengaluru"
    },
    "address": {
        "telephone": "+916789876780",
        "region": "Karnataka",
        "postcode": "560037",
        "line2": "-",
        "line1": "567",
        "lastname": "",
        "firstname": "Test woohoo",
        "email": null,
        "country": "IN",
        "city": "Bengaluru",
        "billToThis": true
    }
}

Thanks,
Kezia
Ashish Singh SFDCAshish Singh SFDC
Hi Kezia,

The response that you're getting and the pattern of wrapper class is not matching. 

Please use https://json2apex.herokuapp.com/ to generate your wrapper class automatically.

Thanks,
Ashish Singh.