-1

I have use-case to call an external web service response in a Batch class. I have desterilized and build the Wrapper from the response like below,

Sample Response

{
    "status": "OK",
    "description": "Match 2 Type",
    "data": [
        {
            "id": "12",
            "name": "dsda",
            "typess": "sad",
            "numberss": "sdada",
            "brand": "fdasd",
            "model": "",
            "year": "",
            "plate_no": "dasad",
            "vin_no": "",
            "timezone": "Something"
         },
         {
            "id": "123",
            "name": "fafa",
            "typess": "afafsa",
            "numberss": "asd",
            "brand": "adasd",
            "model": "",
            "year": "",
            "plate_no": "adsada",
            "vin_no": "",
            "timezone": "Something"
        }
    ]
}

public with sharing class RetrieveInfoService {

public List<WrapperInfo> buildWrapper() {
// Instantiate a new http object
Http http = new Http();
// Instantiate a new HTTP request.
HttpRequest req = new HttpRequest();
req.setEndpoint(InfoEndPoint);
req.setMethod('GET');

System.debug('Response' + http.send(req).getBody());
    
HttpResponse infoResponse = http.send(req);

List<WrapperInfo> lstInfo = new List<WrapperInfo>();

Map<String, Object> mapInfo;
List<Object> lstInfoObject;
if (infoResponse.getStatusCode() == 200) {
    // Deserialize the JSON string into collections of primitive data types.
    mapInfo = (Map<String, Object>) JSON.deserializeUntyped(infoResponse.getBody());
    lstInfoObject = (List<Object>) mapInfo.get('data');

    WrapperInfo info;
    for(Object obj : lstInfoObject) {
      Map<String, Object> p = (Map<String, Object>) obj;

      info = new WrapperInfo();
         for(String s : p.keySet()) {
             if(s.equals('id')) {
                info.Id = (String) p.get(s);
             } else if (s.equals('name')) {
                info.Name = (String) p.get(s);
             } else if (s.equals('typess')) {
                 info.Typess = (String) p.get(s);
             } else if (s.equals('numberss')) {
                 info.simNumber = (String) p.get(s);
             } else if (s.equals('brand')) {
                 info.Brand = (String) p.get(s);
             } else if (s.equals('model')) {
                 info.Model = (String) p.get(s);
             } else if (s.equals('year')) {
                 info.Year = (String) p.get(s);
             } else if (s.equals('plate_no')) {
                 info.PlateNumber = (String) p.get(s);
             } else if (s.equals('vin_no')) {
                 info.VinNumber = (String) p.get(s);
             } else if (s.equals('timezone')) {
                 info.timeZone = (String) p.get(s);
             } 
          }

          lstInfo.add(deviceInfo);
          }
    }

    return  lstInfo; 
}

public class WrapperInfo {

    public String Id {get;set;}
    public String Name {get;set;}
    public String Typess {get;set;}
    public String simNumber {get;set;}
    public String Brand {get;set;}
    public String Model {get;set;}
    public String Year {get;set;}
    public String PlateNumber {get;set;}
    public String VinNumber {get;set;}
    public String timeZone {get;set;}
    }

}

But when I ran the PMD tool against the above implementation I am getting cognitive complexity issue, Is there any better way that I can use to build the wrapper class?

10
  • Convert json to a wrapper using Json2Apex heroku app, and then deserialize deserialize(jsonString, apexType) it to that wrapper class instead of using deserializeUntyped. Nov 23 '20 at 16:23
  • Is there any benefits compare to desterilize method? Nov 23 '20 at 16:31
  • 1
    Or write your own classes (like your "wrapper") and deserialize directly with that (you don't have to generate code in order to do this; we don't use Json2Apex but have plenty of cases where we parse JSON into complex Apex "POTATO" object trees. We take this approach because we have fine control over how the objects are organized and can apply patterns we commonly use).
    – Phil W
    Nov 23 '20 at 16:33
  • 1
    The massive benefits of directly using deserialize is that you don't have to write all that code, it is faster to parse the data and it is generic (it works with any POTATOs you create).
    – Phil W
    Nov 23 '20 at 16:34
  • I see your response has a reserved character and I think this answer your question? How do you deserialize json properties that are reserved words in apex?
    – Raul
    Nov 23 '20 at 16:40
2

Remove all the hand-crafted deserialization code and do something like:

public with sharing class RetrieveInfoService {
    public List<WrapperInfo> buildWrapper() {
        // Instantiate a new http object
        Http http = new Http();

        // Instantiate a new HTTP request.
        HttpRequest req = new HttpRequest();

        req.setEndpoint(InfoEndPoint);
        req.setMethod('GET');
    
        HttpResponse infoResponse = http.send(req);

        System.debug('Response' + infoResponse.getBody());

        if (infoResponse.getStatusCode() == 200) {
            // Deserialize the JSON string into collections of primitive data types.
            Response response = JSON.deserialize(infoResponse.getBody(), Response.class);

            // This could be null or empty, so you might want to do a bit more
            // here before returning the data from the response
            return response.data; 
        }

        return new List<WrapperInfo>();
    }

    public class Response {
        public String status {get; set;}
        public String description {get; set;}
        public List<WrapperInfo> data {get; set;}
    }

    public class WrapperInfo {
        public String id {get;set;}
        public String name {get;set;}
        public String typess {get;set;}
        public String numbers {get;set;}
        public String brand {get;set;}
        public String model {get;set;}
        public String year {get;set;}
        public String plate_no {get;set;}
        public String vin_no {get;set;}
        public String timezone {get;set;}
    }
}

Note that I have made sure there is an object to contain the top-level details, and I have made sure that all the properties for the "wrapper" match the naming in the JSON.

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.