Context: I'm currently toying with the Google Geocode API to break down address strings into a more machine-friendly format. The problem is that neither the user input or API output are 100% consistent, and I would receive less entries in the JSON response than expected. For example, requesting "Times Square NY" gives me 6 address components
"address_components" : [
{
"long_name" : "Manhattan",
"short_name" : "Manhattan",
"types" : [ "political", "sublocality", "sublocality_level_1" ]
},
{
"long_name" : "New York",
"short_name" : "New York",
"types" : [ "locality", "political" ]
},
{
"long_name" : "New York County",
"short_name" : "New York County",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "New York",
"short_name" : "NY",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United States",
"short_name" : "US",
"types" : [ "country", "political" ]
},
{
"long_name" : "10036",
"short_name" : "10036",
"types" : [ "postal_code" ]
}
But, for some reason, "Times Circle NY" gives me 8 address components (notice, for example, how "Times Square NY" does not contain a route entry):
{
"long_name" : "10",
"short_name" : "10",
"types" : [ "street_number" ]
},
{
"long_name" : "Columbus Circle",
"short_name" : "Columbus Cir",
"types" : [ "route" ]
},
{
"long_name" : "Manhattan",
"short_name" : "Manhattan",
"types" : [ "political", "sublocality", "sublocality_level_1" ]
},
{
"long_name" : "New York",
"short_name" : "New York",
"types" : [ "locality", "political" ]
},
{
"long_name" : "New York County",
"short_name" : "New York County",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "New York",
"short_name" : "NY",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United States",
"short_name" : "US",
"types" : [ "country", "political" ]
},
{
"long_name" : "10019",
"short_name" : "10019",
"types" : [ "postal_code" ]
}
My code: To work with the JSON in a more reasonable format, for ex. getting rid of the short_name or accessing a field by component type, I've written an object constructor that goes like this:
class Address {
constructor(googleJson) {
try {
this.state= googleJson["results"][0]["address_components"].filter(el => JSON.stringify(el["types"]) === JSON.stringify(["administrative_area_level_1", "political"]))[0]["short_name"];
}
catch (e) {
this.state= "";
}
try {
this.city= googleJson["results"][0]["address_components"].filter(el => JSON.stringify(el["types"]) === JSON.stringify(["administrative_area_level_2", "political"]))[0]["long_name"];
}
catch (e) {
this.city= "";
}
try {
this.lat = googleJson["results"][0]["geometry"]["location"]["lat"].toString();
}
catch (e) {
this.lat = "";
}
// And so on...
And it works perfectly fine, does its job, but half of my code is just these try/catch pairs. Is there any smarter way to attempt to read multiple potentially empty JSON fields without so much code repetition?
Also, since I'm here, I found the filter I wrote inside each try/catch to be quite legible, but I fear the constructor as a whole would be \$O(n \times m)\$. What other way could I read the JSON in \$O(n + m)\$ and maintain legibility?