makeGeoJSON.pm - Builds GeoJSON files for Google Maps
Drop-in replacement for makeKML.pm:
use makeGeoJSON;
makeGeoJSON->latlongCache("latlong.cache");
makeGeoJSON->useAPI('opencagedata');
my $gj = makeGeoJSON->new({ name => "My Map" });
$gj->add({
name => 'The White House',
desc => 'Where the president lives',
link => 'http://whitehouse.gov/',
style => 'yellowpush',
address => '1600 Pennsylvania Ave NW',
city => 'Washington',
state => 'DC',
});
$gj->write("Map.json");
makeGeoJSON.pm is a drop-in replacement for makeKML.pm that writes a GeoJSON
FeatureCollection instead of KML. It has the same API and uses the same geocoding
infrastructure.
Each feature's properties object contains name, description, link,
and icon (a resolved icon URL for use with the Google Maps Data layer).
GeoJSON is the preferred format for embedding maps in web pages because it is fetched directly by the browser using the Maps Data layer, whereas KmlLayer requires Google's servers to fetch and render the file — a mechanism that has become unreliable and is being phased out.
GeoJSON features need latitude and longitude for each point. makeGeoJSON.pm
can look these up for you by address (geocoding) and caches the results.
Geocoding setup is identical to makeKML.pm.
You will need to register with Google or opencagedata to get a key, but it costs nothing.
For Google, simply visit: https://console.developers.google.com/
Turn on the Geocoding API and look at your credentials, you need to copy the API KEY for server applications.
You can also use opencagedata which allows free geocoding limited to 1/sec by signing up at: https://opencagedata.com/
You can give your key to makeGeoJSON.pm a number of ways:
makeGeoJSON->Key("TheKeyValueThatYouGetFromGoogleOrOpenCageData");
Put the key on a single line in one of the following locations:
google_api_key
.google_api_key
$HOME/.google_api_key
If you're using opencagedata, replace "google" with "opencagedata":
opencagedata_api_key
.opencagedata_api_key
$HOME/.opencagedata_api_key
Or else put the value in a different file and hand it to the library:
makeGeoJSON->KeyFile("KeyFile");
Results are cached in a simple flat file so that addresses don't need to be
looked up again. The default cache file is latlong.cache, changeable with:
makeGeoJSON->latlongCache("CacheFile");
If multiple placemarks are at the same location, makeGeoJSON will offset
the lat/long of each by a small amount so they remain distinguishable on the map.
This amount can be changed (or set to 0) with:
makeGeoJSON->offsetDuplicatePlacemarks(.001); # Default value
Constructs a new makeGeoJSON object.
Options include 'name' (for the map name) and 'file' (to specify file output). Also see 'write'.
Add a place to the GeoJSON file. Places can have a number of keys:
Required fields:
name Name of the place
address Street address
city City name
state State, country or municipality.
At least one of address/city/state is required — enough for a geocoding lookup.
And some optional fields:
link URL
desc Long description (HTML allowed)
coords Latitude,longitude (if not specified, see GEOCODING)
style One of the predefined styles:
redpush bluepush whitepush yellowpush greenpush
ltbluepush purplepush greenpaddle ltbluepaddle bluepaddle
pinkpaddle purplepaddle redpaddle whitepaddle yellowpaddle
Returns 0 on success, -1 if name is missing, -2 if no location can be determined.
Add a custom icon URL as a named style, in addition to the default set.
The URL must be publicly accessible from browsers (use https://).
Required fields:
styleName A unique style name that can now be specified to add()
url URL to the icon image (must be browser-accessible)
Write out the GeoJSON FeatureCollection file.
If a filename is not given, writes to the file specified in new().
Writes GeoJSON (FeatureCollection) instead of KML. Use map.data.loadGeoJson()
instead of google.maps.KmlLayer to display the map.
Icon URLs use maps.gstatic.com/mapfiles/ms2/micons/ — these load correctly
when fetched directly by browsers. The maps.google.com/mapfiles/kml/ URLs
used by makeKML do not load when requested directly by browsers (they only work
when Google's servers render KML).
makeKML.pm has a { vs ( bug that silently breaks all style lookups.
This is corrected here. bluepaddle is also added (it was missing from makeKML).
Descriptions are stored as-is (no KML-specific character cleaning). Non-ASCII
bytes are escaped as \uXXXX in the JSON output, preserving accented characters
correctly.
Use the Google Maps Data layer to display the GeoJSON. Load the API with
async and loading=async to avoid console warnings, and use
window.addEventListener instead of the deprecated addDomListener.
Replace YOUR_KEY with your browser application API key.
<script>
function initialize() {
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center: { lat: 37.77, lng: -122.44 },
zoom: 12
});
var time5 = parseInt((new Date().getTime()) / 5000);
var infoWindow = new google.maps.InfoWindow();
map.data.loadGeoJson('https://example.com/Map.json?a=' + time5);
map.data.setStyle(function(feature) {
return { icon: feature.getProperty('icon') };
});
map.data.addListener('click', function(event) {
var name = event.feature.getProperty('name');
var link = event.feature.getProperty('link');
var desc = event.feature.getProperty('description');
var title = link ? '<a href="' + link + '" target="_blank">' + name + '</a>' : name;
infoWindow.setContent('<b>' + title + '</b><br>' + desc);
infoWindow.setPosition(event.latLng);
infoWindow.open(map);
});
}
window.addEventListener('load', initialize);
</script>
<script async
src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&loading=async">
</script>
<div style="height: 500px; width: 100%;" id="map-canvas"></div>
The ?a=<timestamp> cache-busting parameter ensures browsers reload the JSON
when it changes. Adjust the divisor to control how often (5000 = every 5 seconds,
500000 = every ~8 minutes). Since the browser API key is visible in the page
source, consider restricting it by HTTP referrer in the
Google Developers Console.
Copyright 2004,2020,2026 David Ljung Madison Stellar <http://GetDave.com/>
All rights reserved.
See: http://MarginalHacks.com/