Showing posts with label json. Show all posts
Showing posts with label json. Show all posts

Saturday, September 19, 2015

Consuming a JSON REST result in C# .NET


Yesterday I wrote about an Simple API server for IP Address Information Lookup that I had created in Node.js. This server produces a JSON result that looks like this for IP address 8.8.8.8:

{
   "city":{
      "geoname_id":5375480,
      "names":{
         "en":"Mountain View",
         ...
      }
   },
   "continent":{
      "code":"NA",
      "geoname_id":6255149,
      "names":{
         "de":"Nordamerika",
         "en":"North America",
         ...
      }
   },
   "country":{
      "geoname_id":6252001,
      "iso_code":"US",
      "names":{
         "en":"United States",
         ...
      }
   },
   "location":{
      "latitude":37.386,
      "longitude":-122.0838,
      "metro_code":807,
      "time_zone":"America/Los_Angeles"
   },
   "postal":{
      "code":"94040"
   },
   "registered_country":{
      "geoname_id":6252001,
      "iso_code":"US",
      "names":{
         "en":"United States",
         ...
      }
   },
   "subdivisions":[
      {
         "geoname_id":5332921,
         "iso_code":"CA",
         "names":{
            "en":"California",
            ...
         }
      }
   ]
}

I wanted to consume this end-point in a C# application. A quick search for solutions on how to consume a JSON result from a REST service showed some very complicated ways of doing this. This is a simple solution that I came up with:

// A simple C# class to get the details of an IP address
public class IpApi
{
    public IPInfo GetIPInfo(string ip)
    {
        // Create the URL for the REST endpoint
        string url = "http://localhost:3000/ip/" + ip;
        // Create a .Net WebClient object
        WebClient wc = new WebClient();
        // Get the string result from the REST endpoint
        string json = wc.DownloadString(url);
        // Use Newtonsoft JsonConvert class and its static
        // DeserializeObject method to parse the string into
        // a .Net object
        return JsonConvert.DeserializeObject<IPInfo>(json);
    }
}
// The following classes create the JSON object graph hierarchy
// in static classes. It's a bit tedious looking at the JSON
// object and typing these out. I'd imagine that if you're 
// doing this a lot you could write a tool to generate these
// classes using the JSON as input. Or perhaps there's already
// a tool that does this?
public class Names
{
    // I didn't need the pt-BR and zh-CN key/values from the
    // names so I didn't bother looking up how JsonCovert maps
    // those. 
    public string de, en, fr, ja, ru;
}
public class City
{
    public Names names;
    public int geoname_id;
}
public class Continent
{
    public string code;
    public Names names;
    public int geoname_id;
}
public class Country
{
    public string iso_code;
    public Names names;
    public int geoname_id;
}
public class Location
{
    public decimal latitude;
    public decimal longitude;
    public int metro_code;
    public string time_zone;
}
public class Postal
{
    public string code;
}

public class IPInfo
{
    public City city;
    public Continent continent;
    public Country country;
    public Location location;
    public Postal postal;
    public Country registered_country;
    public Country[] subdivisions;
}



Wednesday, June 26, 2013

Changing the JSON object in an API



Interesting discussion with the development team today about a bug that recently surfaced. The JSON object that was being sent back and forth between the client (browser) and the server changed in structure. For a few hours after the deployment a bunch of exceptions showed up in the logs but as users of the site left and rotated out for new users the exceptions became fewer and finally disappeared.

What had happened was that Ajax calls pages on browsers that had been loaded before the deployment were still communicating with the server using the previous JSON structure while the server was expecting the new JSON object. The code to handle the old JSON object had been removed from the server and not knowing how to deserialize the old object the server was throwing and logging (thankfully) exceptions.

The lesson from this is that you should always provide backward compatibility for one version (iteration) of the code base and then remove that backward compatibility.

The best and easiest way to provide backward compatibility is to have a version key/value pair in your JSON object. Increment the version when you change the JSON structure and perform a switch on the server to handle the previous and current versions. This does, however, require that you thought about this ahead of time and your current live object has a version key/value pair in it.

If not, then you can inspect the object for the known change (e.g. new or removed key) and use an if/else to switch which deserializer you're going to use.

The reason that you want to remove the old code after one iteration is because you want to get rid of dead code as soon as it's dead because it becomes a maintenance nightmare. The longer the dead code is in the code base the more worried everyone is about removing it because nobody can remember if it does anything. While the memory of the previous version is still fresh in your head make sure that old code is killed off. Create a work item in the next project that includes the removal of this code.

Incidentally if you have code that you think is dead but can't be certain (e.g. some code uses reflection to call it or it's an entry point to the application like an API endpoint or web service) then I usually put a log statement in there. Then I put a reminder in my calendar, usually a month out, to search the logging database for that string to see if anything has called it and then I remove it.