1

I am trying to connect to an external system via REST API. The below is the JSON response.

{"coord":{"lon":-0.1257,"lat":51.5085},
"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],
"base":"stations",
"main:{"temp":292.86,"feels_like":287.94,"temp_min":292.04,"temp_max":293.71,"pressure":1027,"humidity":45},
"visibility":10000,"wind":{"speed":6.17,"deg":260},"clouds":{"all":23},"dt":1617027097,"sys":{"type":1,"id":1414,"country":"GB","sunrise":1616996538,"sunset":1617042474},"timezone":3600,"id":2643743,"name":"London","cod":200}

I am parsing it in the below manner but I would like to know if there is any standard method of parsing data. Right now, I somehow feel the below method is inefficient since the JSON string is a mix of list, array of list and objects. Could you please suggest me best practice while parsing the JSON string>

        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('http://api.openweathermap.org/data/2.5/weather?q=London,uk&APPID=8ce9a754cab8e60ec7891a776bab165e');
        request.setMethod('GET');
        HttpResponse response = http.send(request);
        system.debug(response.getBody());
        system.debug(response.getStatusCode());
        
        //Parse the JSON String into a Map
        Map<String, Object> jsonParse = (Map<String, Object>)Json.deserializeUntyped(response.getbody());
        system.debug('jsonMap'+jsonParse);
        
        //Get the weather information - array of list
        List<Object> listObject = (List<Object>)jsonParse.get('weather');
       
        for(Object o: listObject){
            Map<String, Object> weatherMap = (Map<String, Object>)o;
            system.debug('weatherMap '+ weatherMap.get('description'));
            system.debug('weatherMap '+ weatherMap.get('id'));
            system.debug('weatherMap '+ weatherMap.get('main'));
            system.debug('weatherMap '+ weatherMap.get('icon'));
        }
        
        String base = (String)jsonParse.get('base');
        system.debug('base' + base);
        
        Map<String,Object> main = (Map<String,Object>)jsonParse.get('main');
        Decimal temperature = (Decimal)main.get('temp');
        Decimal pressure = (Decimal)main.get('pressure');
        Decimal humidity = (Decimal)main.get('humidity');
        system.debug('temperature '+ temperature);
        system.debug('pressure '+ pressure);
        system.debug('humidity '+ humidity);
        
        Map<String,Object> coord = (Map<String,Object>)jsonParse.get('coord');
        Decimal latitude = (Decimal)coord.get('lat');
        Decimal Longitude = (Decimal)coord.get('lon');
        system.debug('latitude '+ latitude);
        system.debug('longitude '+ longitude);
0
2

You can use JSON2Apex to generate the relevant code for parsing. The ideal solution for parsing is to use classes, which can then be deserialized to directly. I converted the code from there to a simpler implicit parser (because of an apparent bug in JSON2Apex), which gives us:

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

public class WeatherApiResponse {
    public class Main {
        public Double temp;
        public Double feels_like; 
        public Double temp_min; 
        public Double temp_max; 
        public Integer pressure; 
        public Integer humidity; 
    }
    public class Clouds {
        public Integer all; 
    }
    public class Sys {
        public Integer type;
        public Integer id; 
        public String country; 
        public Integer sunrise; 
        public Integer sunset; 
    }
    public class Weather {
        public Integer id; 
        public String main; 
        public String description; 
        public String icon;     
    }
    public class Coord {
        public Double lon; 
        public Double lat; 
    }
    public class Wind {
        public Double speed; 
        public Integer deg; 
    }
    
    public Coord coord; 
    public List<Weather> weather; 
    public String base; 
    public Main main; 
    public Integer visibility; 
    public Wind wind; 
    public Clouds clouds; 
    public Integer dt; 
    public Sys sys; 
    public Integer timezone; 
    public Integer id; 
    public String name; 
    public Integer cod; 
    public static WeatherApiResponse parse(String jsonString) {
        return (WeatherApiResponse)JSON.deserialize(jsonString, WeatherApiResponse.class);
    }
}

To use this, you just:

 WeatherApiResponse weatherData = WeatherApiResponse.parse(response.getbody());
 System.debug(weatherData.main.temp); // as an example

This gives you compile-time safety to make sure you don't have any parsing problems.

3
  • Hi sfdcfox thanks for your answer. Thank you for teaching me the easiest way to parse. I’ll try it out. You’re the best! – Krishnamurthy Apr 1 at 7:57
  • Hi @sfdcfox, can you please explain the last two lines of code as to what it does? WeatherApiResponse weatherData = WeatherApiResponse.parse(response.getbody()); System.debug(weatherData.main.temp); Why do you need to instantiate WeatherAPIResponse class to call the static method? – Krishnamurthy Apr 2 at 10:27
  • @Krishnamurthy There's no direct instantiation here; we call the static method as a helper method to parse our JSON for us. This is the code you call instead of JSON.deseriaizeUntyped(...);. – sfdcfox Apr 2 at 11:06
0

You can create a class with the structure of your JSON and parse the response directly to a instance of your class.

public class YourClassEqualsToJSON{
  public String status;
}

YourClassEqualsToJSON r = (Response) JSON.parse({"status":"something"}/*or response.getBody() */, YourClassEqualsToJSON.class);

take a look at https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_class_System_Json.htm

1
  • I’m not able to understand your answer. Would you mind changing the code based on my JSON? – Krishnamurthy Mar 31 at 14:45

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