0

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!

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @Maerlyn, I actually set the filesize to something like 1,000,000 because I didn't think it could possibly be any longer than that. But this suggestion works. :)
That only cures the symptom, not the reason behind it. Only good for a short term, and it'll come back to bite you whenever you move to a server with disabled allow_url_fopen.
0

For me your string are decoded perfectly. Maybe the response are encoding in UTF-8 and exist a B.O.M (Byte Order Mark) character in the string. In this case, the string is not correctly a JSON formated structure (see RFC 4627).

In his place I would write a few more lines to see if this is the problem. You can strip B.O.M characteres packing CCC inna bynary string. Call this function recursively:

function removeBOM($str=""){
        if(substr($str, 0,3) == pack("CCC",0xef,0xbb,0xbf)) {
                $str=substr($str, 3);
        }
        return $str;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.