Get World Countries and Cities Weather with their Geolocations (API -JSON) Part II.


So now we have our JSON response displayed on a Visualforce page, but let’s be honest… is not readable for everyone. We are going to make a few changes to our class and write extra code to make sure that users can read and interact with the data we are receiving from our HTTP call.

We are not going to add every single field from the response into this page, instead, we are going to use the one URL that comes as part of the response to display things in a more proper way. We are going to capture some of the most simple errors on this page, nothing fancy. The first thing we are going to do is to build an Apex class from the response. We can accomplish this by copying our response and using this site. JSON2Apex is a well-known website to transform your JSON responses into Apex Classes, it will save us a lot of time. 

After converting your JSON into APEX you will have a pretty long apex class. We are going to use a small portion of that call for this example.

Check out what it is that we need from that apex class coming from JSON2Apex. I created a new class with the name ‘JSONWeatherLocation’ and from the apex class, I’m going to use the ‘location’ class as you can see.
This class contains a number of fields that are the fields I want to display on my Visualforce page.

/**************************************************************
* @Author   : Carlos Naranjo 
* @Website  : http://ccloudonline.nl - http://ccloudonline.com
*
***************************************************************/
 public class JSONWeatherLocation {

   public location location{get;set;}
  
    public class location{
 
      public String magic{get;set;}
      public String wmo{get;set;}
      public String zip{get;set;}
      public String l{get;set;}
      public String lon{get;set;}
      public String requesturl{get;set;}
      public String lat{get;set;}
      public String wuiurl{get;set;}
      public String tz_long{get;set;}
      public String country_name{get;set;}
      public String state{get;set;}
      public String country_iso3166{get;set;}
      public String city{get;set;}
      public String country{get;set;}
      public String tz_short{get;set;}
     }
 }

After this is done we can save our JSONWeatherLocation class and start working on the next apex code that we will use as the controller for our Visualforce page. This is not the same class that we used in the previous example.

This is the new class we are going to use. The most important factor is that we have our HTPP request and some ApexPage error message in case that we find any empty values on Country or/and City. This class is not covering all possible errors, but this one is to illustrate how we can display errors in your Visualforce page.

/**************************************************************
* @Author   : Carlos Naranjo 
* @Website  : http://ccloudonline.nl - http://ccloudonline.com
*
***************************************************************/
public class JSONWeatherDesesializeClass {
        
                 public String magic{get;set;}
                 public String wmo{get;set;}
                 public String zip{get;set;}
                 public String l{get;set;}
                 public String lon{get;set;}
                 public String requesturl{get;set;}
                 public String lat{get;set;}
                 public String wuiurl{get;set;}
                 public String tz_long{get;set;}
                 public String country_name{get;set;}
                 public String state{get;set;}
                 public String country_iso3166{get;set;}
                 public String city{get;set;}
                 public String country{get;set;}
                 public String tz_short{get;set;}
 
                 public String countryImput {get;set;}
                 public String cityImput{get;set;}
                 
 
     public JSONWeatherDesesializeClass()
     {
         countryImput ='Spain';
         cityImput='Sevilla';
     }
                    
         public void deserialize()
         {
         
         if((countryImput=='' && cityImput =='') || (countryImput=='') || (cityImput=='')){
           ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'Sorry, you need to insert country and city.'));
                   
         }else{      
        
         String long_running_service_URL =
         'http://api.wunderground.com/api/48ba9f7756d42102/geolookup/conditions/forecast/q/';
 
         HttpRequest req = new HttpRequest();
         req.setEndpoint(long_running_service_URL+ countryImput + '/' + cityImput +'.json');
         req.setMethod('GET');

         Http http = new Http();
         HttpResponse res = http.send(req);
         String responseBody = res.getBody();

         JSONWeatherLocation wLoc = (JSONWeatherLocation)JSON.deserialize(responseBody, JSONWeatherLocation.class);

        
         city            = wLoc.location.city;
         country         = wLoc.location.country;
         zip             = wloc.location.zip; 
         magic           = wLoc.location.magic;
         wmo             = wLoc.location.wmo;
         country_name    = wLoc.location.country_name;
         lat             = wLoc.location.lat;
         state           = wLoc.location.state;
         lon             = wLoc.location.lon;
         requesturl      = wLoc.location.requesturl;
         tz_long         = wLoc.location.tz_long;
         tz_short        = wLoc.location.tz_short;
         country_iso3166 = wLoc.location.country_iso3166;
         l               = wLoc.location.l;
         wuiurl          = wLoc.location.wuiurl;
        }

   }
 }

The functionality is the same than on the previous example, the user inserts a Country and a City and we will display whether a geolocation information for those values.

The last part is our Visualforce page. I also added a “Loading” effect to the page so our users can see that something is happing when they are waiting. You can get this package here.

So, here is the page:

<apex:page controller="JSONWeatherDesesializeClass" showHeader="true" sidebar="false" docType="html-5.0">
 <apex:pageMessages id="errors" />
 <!-- Import Necessary Jquery js File and StyleSheets-->
    <apex:includeScript value="{!URLFOR($Resource.jQuery, 'js/jquery-1.6.2.min.js')}"/>
    <apex:includeScript value="{!URLFOR($Resource.jQuery, 'js/jquery-ui-1.8.16.custom.min.js')}"/>
    <apex:includeScript value="{!URLFOR($Resource.jqPlugin, '/jquery.blockUI.js')}"/>
    <apex:stylesheet value="{!URLFOR($Resource.jQuery, 'css/ui-lightness/jquery-ui-1.8.16.custom.css')}"/>
    
    <script>
        $j = jQuery.noConflict();
        
        //function to block the whole page
        function blockPage(){ 
            $j.blockUI({ message: '<img src="/img/loading32.gif" /><h1> Loading...</h1>', 
                css: { 
                 border: 'none', 
                 padding: '15px',  
                 '-webkit-border-radius': '10px', 
                 '-moz-border-radius': '10px', 
                 opacity: .9
                } 
            }); 
            return false;
        }
        
        //function to unblock the page
        function unblockPage(){
            $j.unblockUI();
        }
    </script>


<apex:form >
<apex:actionStatus onstart="blockPage()" onstop="unblockPage()" id="blockUI"/>
     <apex:pageBlock title="Insert Country and City" >
         <apex:pageblockButtons location="top" >
            <apex:commandButton value="Geolocation and Weather Service" action="{!deserialize}" reRender="weatherBlock,theGraph,errors" status="blockUI"/>
            </apex:pageblockButtons>
              <apex:pageBlockSection columns="1">
           
            <apex:input label="Country" value="{!countryImput}"/>
            <apex:input label="City" value="{!cityImput}"/>
            
              </apex:pageBlockSection>
            </apex:pageBlock>

<apex:pageBlock title="JSON Deserialize Response">
            

            <apex:pageBlockSection id="weatherBlock" columns="2">
            <apex:facet name="header">Country: {!country_name}</apex:facet> 
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="City:" for="city"/>                
                    <apex:outputText value="{!city}" id="city" /> 
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Zip Code:" for="zip"/>                
                    <apex:outputText value="{!zip}" id="zip" />     
            </apex:pageBlockSectionItem>            
             <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Country Name:" for="country_name"/>     
                    <apex:outputText value="{!country_name}" id="countryname" />     
            </apex:pageBlockSectionItem>             
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Magic:" for="magic"/>                
                    <apex:outputText value="{!magic}" id="magic" />     
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Latitude:" for="lat"/>                
                    <apex:outputText value="{!lat}" id="latitude" />     
            </apex:pageBlockSectionItem> 
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Wmo:" for="wmo"/>                
                    <apex:outputText value="{!wmo}" id="wmo" />     
            </apex:pageBlockSectionItem> 
             <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Longitude:" for="longitude"/>          
                    <apex:outputText value="{!lon}" id="longitude" />     
            </apex:pageBlockSectionItem>  
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="State:" for="state"/>                
                    <apex:outputText value="{!state}" id="state" />     
            </apex:pageBlockSectionItem>  
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Request URL:" for="requesturl"/>       
                    <apex:outputText value="{!requesturl}" id="requesturl" />     
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="TZ Long :" for="tz_long"/>       
                    <apex:outputText value="{!tz_long}" id="tz_long" />     
            </apex:pageBlockSectionItem>   
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="TZ Short :" for="tz_short"/>       
                    <apex:outputText value="{!tz_short}" id="tz_short" />     
            </apex:pageBlockSectionItem> 
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Country ISO :" for="country_iso3166"/>    
                    <apex:outputText value="{!country_iso3166}" id="country_iso3166" />     
            </apex:pageBlockSectionItem> 
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="L :" for="l"/>    
                    <apex:outputText value="{!l}" id="l" />     
            </apex:pageBlockSectionItem> 
            <apex:pageBlockSectionItem >
                    <apex:outputLabel value="Wui URL :" for="wuiurl"/>    
                    <apex:outputText value="{!wuiurl}" id="wuiurl" />     
            </apex:pageBlockSectionItem>  
            
         </apex:pageBlockSection>
              <apex:pageBlock title="The Graph" id="theGraph">
                 <apex:iframe src="{!wuiurl}" scrolling="true" id="theIframe"/> 
             </apex:pageBlock>
    </apex:pageBlock>
  </apex:form>
</apex:page>

We now have all the components we need to make our JSON response more user-friendly :).
Before we had a raw JSON response on a Visualforce page, now we have a UI with several functionalities.

We have moved things a bit around and now the page looks like this:

If we insert our Country and City and hit our Geolocation and Weather Service button a loading icon will let the user knows that we are contacting the service to get a response back to the Visualforce page.

Something like this:

The loading effect will be active until we get a response. After that our page will be loaded with all the information for the fields that are on the first section plus an iframe that will allow the user to interact will the weather underground site.

Check it out:

**


**

The last screenshot is to show you what happen it you leave either the Country or the City empty, or both:


**

Well, that’s all!

I hope you enjoyed this tutorial!

Leave a Reply

Your email address will not be published. Required fields are marked *