JSON, LINQ, and expected objects...

Sep 11, 2009 at 1:05 PM

I'm using Google Maps' Geocoding interface. After throwing my hands in the air in frustration trying to get LINQ to XML to behave, I switched to JSON. This has been quite a bit less headache to setup than the LINQ to XML portion. Except that now I've run into a problem. I'm processing a list of addresses, and a couple of the addresses don't actually have Street Addresses. I still need to process these as having a geocode to at least their ZIP code works. The issue is that if I don't send across a street address, Google doesn't return a node for Thouroughfare.

Here's a complete Google JSON return:

{
  "name": "Address: 435 North Mulford Road Rockford, IL 61107",
  "Status": {
    "code": 200,
    "request": "geocode"
  },
  "Placemark": [ {
    "id": "p1",
    "address": "435 N Mulford Rd, Rockford, IL 61107, USA",
    "AddressDetails": {
   "Accuracy" : 8,
   "Country" : {
      "AdministrativeArea" : {
         "AdministrativeAreaName" : "IL",
         "SubAdministrativeArea" : {
            "Locality" : {
               "LocalityName" : "Rockford",
               "PostalCode" : {
                  "PostalCodeNumber" : "61107"
               },
               "Thoroughfare" : {
                  "ThoroughfareName" : "435 N Mulford Rd"
               }
            },
            "SubAdministrativeAreaName" : "Winnebago"
         }
      },
      "CountryName" : "USA",
      "CountryNameCode" : "US"
   }
},
    "ExtendedData": {
      "LatLonBox": {
        "north": 42.2753076,
        "south": 42.2690124,
        "east": -88.9964645,
        "west": -89.0027597
      }
    },
    "Point": {
      "coordinates": [ -88.9995886, 42.2721596, 0 ]
    }
  } ]
}
And here's an example of their return without a street address:
{
  "name": "Address:Clarion Associates, Chicago, IL 60605",
  "Status": {
    "code": 200,
    "request": "geocode"
  },
  "Placemark": [ {
    "id": "p1",
    "address": "Chicago, IL 60605, USA",
    "AddressDetails": {
   "Accuracy" : 5,
   "Country" : {
      "AdministrativeArea" : {
         "AdministrativeAreaName" : "IL",
         "SubAdministrativeArea" : {
            "Locality" : {
               "LocalityName" : "Chicago",
               "PostalCode" : {
                  "PostalCodeNumber" : "60605"
               }
            },
            "SubAdministrativeAreaName" : "Cook"
         }
      },
      "CountryName" : "USA",
      "CountryNameCode" : "US"
   }
},
    "ExtendedData": {
      "LatLonBox": {
        "north": 41.8770540,
        "south": 41.8522760,
        "east": -87.6055990,
        "west": -87.6343840
      }
    },
    "Point": {
      "coordinates": [ -87.6211061, 41.8677988, 0 ]
    }
  } ]
}
(By the way, took me a while to figure out the silly ["Placemark"][0]["AddressDetails"] bit, not your fault, but I hope there's some reason that Google makes an 'array' out of that)

Anyways, here's the C# LINQ code I'm using...
json = JObject.Parse(jsonText);
retVal = new GeoData
{
    SearchAddress = (string)json["Placemark"][0]["AddressDetails"]["Country"]["AdministrativeArea"]["SubAdministrativeArea"]["Locality"]["LocalityName"]["Thouroughfare"]["ThoroughfareName"],
    Accuracy = (GeoAddressAccuracy)Int16.Parse((string)json["Placemark"][0]["AddressDetails"]["Accuracy"]),
    Status = (GeoStatusCode)Int16.Parse((string)json["Status"]["code"])
    rawCoordinates = (string)json["Placemark"]["Point"][0]["coordinates"]
};
The error I get is an 'Object Expected' error when I get to the one that doesn't have an address. Obviously, I could use an object == null ? string.empty : object.value construct,
but then that would just look UGLY. I was hoping there was an easier/quicker/prettier way to do this. Is there a way to format the json object against an expceted structure? Thus
filling in missing paramaters with empty string or null? Or is there a built in 'This object doesn't exist, return empty' method in Json.NET?

Thanks for any/all help! Also, thanks for Json.NET...seems really really useful, and as I said, I got it up using LINQ quicker (and actually got it up period) than XML.


        
    
Coordinator
Sep 11, 2009 at 8:31 PM

No. I'd create a method and hide the unpleasantness of the ternary operator in there.

Sep 14, 2009 at 9:58 PM

I've been beating my head against a wall and have not been able to figure this out. I tried quite a number of different things...

Oh...and then I found out that I had mis-spelled Thouroughfare  in my code. *Sigh* Oh and json["Placemark"]["Point"][0] should have the Point and 0 switched.

 

I finally did this for a method:

 

private static string parseAddress(JObject jObj)
{
  string retVal;
  try
  {
    retVal = jObj["Thoroughfare"].Value<string>("ThoroughfareName");
  }
  catch
  {
    retVal = string.Empty;
  }
    return retVal;
}

I called it with:

 

SearchAddress = parseAddress((JObject)json["Placemark"].First["AddressDetails"]["Country"]["AdministrativeArea"]["SubAdministrativeArea"]["Locality"]),

Seems to work. I also changed all the [0] to .First, that seems to look nicer in the code.