openstreetmap json geolocation using java

A viable free alternative to google’s geolocation api is openstreetmap’s nominatim functionality. The service recommends restricting the frequency of requests to 1 per second, so if nothing else, this is a viable failover alternative to google’s geolocation api.

The code below may be used to query openstreetmap’s nominatim database for latitude/longitude information. It uses the jackson library for json parsing.

If you are using maven, add:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-jaxrs</artifactId>
    <version>1.9.4</version>
</dependency>

to your pom.xml file’s dependencies to satisfy the import statements in the class below.

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.codehaus.jackson.map.ObjectMapper;

public class OpenStreetMapGeoCodeJacksonParser {

    private static final String LATITUDE = "lat";
    private static final String LONGITUDE = "lon";

    public LatLng parse(final InputStream jsonStream) {
        LatLng coordinate = null;
        final ObjectMapper mapper = new ObjectMapper();
        try {
            final List<Object> dealData = mapper.readValue(jsonStream, List.class);
            if (dealData != null && dealData.size() == 1) {
                final Map< String, Object > locationMap = (Map< String, Object >) dealData.get(0);
                if (locationMap != null && locationMap.containsKey(LATITUDE) && locationMap.containsKey(LONGITUDE)) {
                    final double lat = Double.parseDouble(locationMap.get(LATITUDE).toString());
                    final double lng = Double.parseDouble(locationMap.get(LONGITUDE).toString());
                    coordinate = new LatLng(lat, lng);
                 }
             } else {
                 Logger.getLogger(OpenStreetMapGeoCodeJacksonParser.class.getName()).log(Level.SEVERE, "NO RESULTS", "NO RESULTS");
             }
         } catch (Exception ex) {
             Logger.getLogger(OpenStreetMapGeoCodeJacksonParser.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
         }
    return coordinate;
    }

    public LatLng parse(String rawAddress) {
        InputStream is = null;
        LatLng coords = null;

        if (rawAddress != null && rawAddress.length() > 0 ) {
            try {
                String address = URLEncoder.encode(rawAddress, "utf-8");
                String geocodeURL = "http://nominatim.openstreetmap.org/search?format=json&limit=1&polygon=0&addressdetails=0&email=contact@EMAIL.ME&countrycodes=us&q=";
                //query google geocode api
                String formattedUrl = geocodeURL + address;
                URL geocodeUrl = new URL(formattedUrl);
                is = geocodeUrl.openStream();
                coords = parse(is);
            } catch (IOException ex) {
                Logger.getLogger(OpenStreetMapGeoCodeJacksonParser.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                try {
                    is.close();
                } catch (IOException ex) {
                    Logger.getLogger(OpenStreetMapGeoCodeJacksonParser.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return coords;
    }

    public static void main(final String[] args) {
        final String rawAddress = "Los Angeles, CA";
        System.out.println(new OpenStreetMapGeoCodeJacksonParser().parse(rawAddress));
    }
}

Please make sure to substitute a valid email address into the geocodeURL’s email GET parameter.

Finally, the LatLng.java class holds the latitude-longitude information.

import java.io.Serializable;

/**
 *
 * @author mdanter
 */
public class LatLng implements Serializable{

    private static final long serialVersionUID = 16549987563L;

    private double lat;
    private double lng;

    public LatLng(final double lat, final double lng) {
        this.lat = lat;
        this.lng = lng;
    }

    public double getLat() {
        return lat;
    }

    public void setLat(final double lat) {
        this.lat = lat;
    }

    public double getLng() {
        return lng;
    }

    public void setLng(final double lng) {
        this.lng = lng;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final LatLng other = (LatLng) obj;
        if (Double.doubleToLongBits(this.lat) != Double.doubleToLongBits(other.lat)) {
            return false;
        }
        if (Double.doubleToLongBits(this.lng) != Double.doubleToLongBits(other.lng)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 53 * hash + (int) (Double.doubleToLongBits(this.lat) ^ (Double.doubleToLongBits(this.lat) >>> 32));
        hash = 53 * hash + (int) (Double.doubleToLongBits(this.lng) ^ (Double.doubleToLongBits(this.lng) >>> 32));
        return hash;
    }

}

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>