Search code examples
phpjsongoogle-maps-api-3google-geocoder

PHP Script fails to parse JSON returned by Google Maps Geocoder API if multiple results are returned by Geocoder


I have a PHP script that attempts to read and parse JSON strings returned from Google's Geocoder API. The script works fine for most addresses but runs into trouble in a few occasions where Google's Geocoder API returns multiple results for a given address.

This is my code:

$mGeoFile = fopen("http://maps.googleapis.com/maps/api/geocode/json?address=" . str_replace(" ", "+", $mAddress0) . "&sensor=false", "r");       
$mGeoFileJSON = fread($mGeoFile, 10000);
fclose($mGeoFile);
$mGeocode_array = json_decode($mGeoFileJSON, true);

var_dump($mGeocode_array);
echo "<br />";
var_dump($mGeocode_array['results'][0]['geometry']['location']);

Which prints this for "115 Chestnut Street Upton, MA" (passed in $mAddress0):

array(2) { ["status"]=> string(2) "OK" ["results"]=> array(1) { [0]=> array(4) { ["types"]=> array(1) { [0]=> string(14) "street_address" } ["formatted_address"]=> string(37) "115 Chestnut St, Upton, MA 01568, USA" ["address_components"]=> array(8) { [0]=> array(3) { ["long_name"]=> string(3) "115" ["short_name"]=> string(3) "115" ["types"]=> array(1) { [0]=> string(13) "street_number" } } [1]=> array(3) { ["long_name"]=> string(11) "Chestnut St" ["short_name"]=> string(11) "Chestnut St" ["types"]=> array(1) { [0]=> string(5) "route" } } [2]=> array(3) { ["long_name"]=> string(5) "Upton" ["short_name"]=> string(5) "Upton" ["types"]=> array(2) { [0]=> string(8) "locality" [1]=> string(9) "political" } } [3]=> array(3) { ["long_name"]=> string(5) "Upton" ["short_name"]=> string(5) "Upton" ["types"]=> array(2) { [0]=> string(27) "administrative_area_level_3" [1]=> string(9) "political" } } [4]=> array(3) { ["long_name"]=> string(9) "Worcester" ["short_name"]=> string(9) "Worcester" ["types"]=> array(2) { [0]=> string(27) "administrative_area_level_2" [1]=> string(9) "political" } } [5]=> array(3) { ["long_name"]=> string(13) "Massachusetts" ["short_name"]=> string(2) "MA" ["types"]=> array(2) { [0]=> string(27) "administrative_area_level_1" [1]=> string(9) "political" } } [6]=> array(3) { ["long_name"]=> string(13) "United States" ["short_name"]=> string(2) "US" ["types"]=> array(2) { [0]=> string(7) "country" [1]=> string(9) "political" } } [7]=> array(3) { ["long_name"]=> string(5) "01568" ["short_name"]=> string(5) "01568" ["types"]=> array(1) { [0]=> string(11) "postal_code" } } } ["geometry"]=> array(4) { ["location"]=> array(2) { ["lat"]=> float(42.1476896) ["lng"]=> float(-71.5863099) } ["location_type"]=> string(18) "RANGE_INTERPOLATED" ["viewport"]=> array(2) { ["southwest"]=> array(2) { ["lat"]=> float(42.1445379) ["lng"]=> float(-71.5894495) } ["northeast"]=> array(2) { ["lat"]=> float(42.1508332) ["lng"]=> float(-71.5831542) } } ["bounds"]=> array(2) { ["southwest"]=> array(2) { ["lat"]=> float(42.1476815) ["lng"]=> float(-71.5863099) } ["northeast"]=> array(2) { ["lat"]=> float(42.1476896) ["lng"]=> float(-71.5862938) } } } } } } 
array(2) { ["lat"]=> float(42.1476896) ["lng"]=> float(-71.5863099) }

Also the Geocoder returns the following JSON string for "115 Chestnut Street Upton, MA"

{
  "status": "OK",
  "results": [ {
    "types": [ "street_address" ],
    "formatted_address": "115 Chestnut St, Upton, MA 01568, USA",
    "address_components": [ {
      "long_name": "115",
      "short_name": "115",
      "types": [ "street_number" ]
    }, {
      "long_name": "Chestnut St",
      "short_name": "Chestnut St",
      "types": [ "route" ]
    }, {
      "long_name": "Upton",
      "short_name": "Upton",
      "types": [ "locality", "political" ]
    }, {
      "long_name": "Upton",
      "short_name": "Upton",
      "types": [ "administrative_area_level_3", "political" ]
    }, {
      "long_name": "Worcester",
      "short_name": "Worcester",
      "types": [ "administrative_area_level_2", "political" ]
    }, {
      "long_name": "Massachusetts",
      "short_name": "MA",
      "types": [ "administrative_area_level_1", "political" ]
    }, {
      "long_name": "United States",
      "short_name": "US",
      "types": [ "country", "political" ]
    }, {
      "long_name": "01568",
      "short_name": "01568",
      "types": [ "postal_code" ]
    } ],
    "geometry": {
      "location": {
        "lat": 42.1476896,
        "lng": -71.5863099
      },
      "location_type": "RANGE_INTERPOLATED",
      "viewport": {
        "southwest": {
          "lat": 42.1445379,
          "lng": -71.5894495
        },
        "northeast": {
          "lat": 42.1508332,
          "lng": -71.5831542
        }
      },
      "bounds": {
        "southwest": {
          "lat": 42.1476815,
          "lng": -71.5863099
        },
        "northeast": {
          "lat": 42.1476896,
          "lng": -71.5862938
        }
      }
    }
  } ]
}

I run into a problem with an address such as 50 Franklin Street Boston, MA for which the google Geocoder API returns:

{
  "status": "OK",
  "results": [ {
    "types": [ "street_address" ],
    "formatted_address": "50 Franklin St, Boston, MA 02110, USA",
    "address_components": [ {
      "long_name": "50",
      "short_name": "50",
      "types": [ "street_number" ]
    }, {
      "long_name": "Franklin St",
      "short_name": "Franklin St",
      "types": [ "route" ]
    }, {
      "long_name": "Boston",
      "short_name": "Boston",
      "types": [ "locality", "political" ]
    }, {
      "long_name": "Boston",
      "short_name": "Boston",
      "types": [ "administrative_area_level_3", "political" ]
    }, {
      "long_name": "Suffolk",
      "short_name": "Suffolk",
      "types": [ "administrative_area_level_2", "political" ]
    }, {
      "long_name": "Massachusetts",
      "short_name": "MA",
      "types": [ "administrative_area_level_1", "political" ]
    }, {
      "long_name": "United States",
      "short_name": "US",
      "types": [ "country", "political" ]
    }, {
      "long_name": "02110",
      "short_name": "02110",
      "types": [ "postal_code" ]
    } ],
    "geometry": {
      "location": {
        "lat": 42.3556540,
        "lng": -71.0585261
      },
      "location_type": "ROOFTOP",
      "viewport": {
        "southwest": {
          "lat": 42.3525064,
          "lng": -71.0616737
        },
        "northeast": {
          "lat": 42.3588016,
          "lng": -71.0553785
        }
      }
    }
  }, {
    "types": [ "street_address" ],
    "formatted_address": "50 Franklin St, Boston, MA 02122, USA",
    "address_components": [ {
      "long_name": "50",
      "short_name": "50",
      "types": [ "street_number" ]
    }, {
      "long_name": "Franklin St",
      "short_name": "Franklin St",
      "types": [ "route" ]
    }, {
      "long_name": "Boston",
      "short_name": "Boston",
      "types": [ "locality", "political" ]
    }, {
      "long_name": "Boston",
      "short_name": "Boston",
      "types": [ "administrative_area_level_3", "political" ]
    }, {
      "long_name": "Suffolk",
      "short_name": "Suffolk",
      "types": [ "administrative_area_level_2", "political" ]
    }, {
      "long_name": "Massachusetts",
      "short_name": "MA",
      "types": [ "administrative_area_level_1", "political" ]
    }, {
      "long_name": "United States",
      "short_name": "US",
      "types": [ "country", "political" ]
    }, {
      "long_name": "02122",
      "short_name": "02122",
      "types": [ "postal_code" ]
    } ],
    "geometry": {
      "location": {
        "lat": 42.2871370,
        "lng": -71.0400105
      },
      "location_type": "ROOFTOP",
      "viewport": {
        "southwest": {
          "lat": 42.2839894,
          "lng": -71.0431581
        },
        "northeast": {
          "lat": 42.2902846,
          "lng": -71.0368629
        }
      }
    }
  }, {
    "types": [ "street_address" ],
    "formatted_address": "50 Franklin St, Boston, MA 02129, USA",
    "address_components": [ {
      "long_name": "50",
      "short_name": "50",
      "types": [ "street_number" ]
    }, {
      "long_name": "Franklin St",
      "short_name": "Franklin St",
      "types": [ "route" ]
    }, {
      "long_name": "Boston",
      "short_name": "Boston",
      "types": [ "locality", "political" ]
    }, {
      "long_name": "Boston",
      "short_name": "Boston",
      "types": [ "administrative_area_level_3", "political" ]
    }, {
      "long_name": "Suffolk",
      "short_name": "Suffolk",
      "types": [ "administrative_area_level_2", "political" ]
    }, {
      "long_name": "Massachusetts",
      "short_name": "MA",
      "types": [ "administrative_area_level_1", "political" ]
    }, {
      "long_name": "United States",
      "short_name": "US",
      "types": [ "country", "political" ]
    }, {
      "long_name": "02129",
      "short_name": "02129",
      "types": [ "postal_code" ]
    } ],
    "geometry": {
      "location": {
        "lat": 42.3785674,
        "lng": -71.0668132
      },
      "location_type": "RANGE_INTERPOLATED",
      "viewport": {
        "southwest": {
          "lat": 42.3754150,
          "lng": -71.0699535
        },
        "northeast": {
          "lat": 42.3817103,
          "lng": -71.0636583
        }
      },
      "bounds": {
        "southwest": {
          "lat": 42.3785579,
          "lng": -71.0668132
        },
        "northeast": {
          "lat": 42.3785674,
          "lng": -71.0667986
        }
      }
    }
  }, {
    "types": [ "street_address" ],
    "formatted_address": "50 Franklin St, Boston, MA 02136, USA",
    "address_components": [ {
      "long_name": "50",
      "short_name": "50",
      "types": [ "street_number" ]
    }, {
      "long_name": "Franklin St",
      "short_name": "Franklin St",
      "types": [ "route" ]
    }, {
      "long_name": "Boston",
      "short_name": "Boston",
      "types": [ "locality", "political" ]
    }, {
      "long_name": "Boston",
      "short_name": "Boston",
      "types": [ "administrative_area_level_3", "political" ]
    }, {
      "long_name": "Suffolk",
      "short_name": "Suffolk",
      "types": [ "administrative_area_level_2", "political" ]
    }, {
      "long_name": "Massachusetts",
      "short_name": "MA",
      "types": [ "administrative_area_level_1", "political" ]
    }, {
      "long_name": "United States",
      "short_name": "US",
      "types": [ "country", "political" ]
    }, {
      "long_name": "02136",
      "short_name": "02136",
      "types": [ "postal_code" ]
    } ],
    "geometry": {
      "location": {
        "lat": 42.2526044,
        "lng": -71.1332635
      },
      "location_type": "RANGE_INTERPOLATED",
      "viewport": {
        "southwest": {
          "lat": 42.2494625,
          "lng": -71.1364052
        },
        "northeast": {
          "lat": 42.2557577,
          "lng": -71.1301100
        }
      },
      "bounds": {
        "southwest": {
          "lat": 42.2526044,
          "lng": -71.1332635
        },
        "northeast": {
          "lat": 42.2526158,
          "lng": -71.1332517
        }
      }
    },
    "partial_match": true
  } ]
}

And my script returns:

NULL 
NULL

Any ideas what might be going on? Thanks!


Solution

  • It's quite possible that the response gets over 10k characters, in that case you're trying to decode an invalid JSON string. Make sure you're reading the whole stream before decoding. The simplest way is to use file_get_contents instead of fopen/fread/fclose. On the long run you should switch to curl.