ProgrammingTutorial

Generate GeoJson in Java with Jackson JSON without third party geojson libraries

In this article we are going to look at a code snippet for generating geojson data from ArrayList of POJOs with basic JSON Parsers such as Jackson JSON, Gson, Json-simple – no third party geojson library (we will look at these later and compare performance). For this article I choose to use Jackson JSON API as this code was written under Spring Boot project which comes with Jackson as the defaul JSON serializer.

About Jackson JSON Java Parser

Jackson is a suite of data-processing tools for Java (and the JVM platform). It includes the flagship streaming JSON parser / generator library, matching data-binding library (POJOs to and from JSON) and additional data format modules to process data encoded in AvroBSON,CBORCSVSmile(Java) PropertiesProtobufXML or YAML; and even the large set of data format modules to support data types of widely used data types such as GuavaJodaPCollections and many, many more. Read more on the project Github wiki.

Jackson in Numbers

Jackson JSON Java Parser is very popular and is used in Spring framework asthe default.

Features of Jackson

Visit this link for more details on the features of Jackson JSON that are categorized as ;-

High level features affecting jackson-databind components directly

Low level features affecting  Streaming API behavior.

About GeoJson

Geojson is a geospatial data interchange format based on JavaScript Object Notation (JSON). It defines several types of JSON objects and the manner in which they are combined to represent data about geographic features, their properties, and their spatial extents. GeoJSON uses a geographic coordinate reference system, World Geodetic System 1984, and units of decimal degrees.

READ  Why PostGIS is the love of GISers

Read more here about the geographic data representation in Geojson, the geometry type and the types Feature and FeatureCollection.

Example

A GeoJSON FeatureCollection:

  {
       "type": "FeatureCollection",
       "features": [{
           "type": "Feature",
           "geometry": {
               "type": "Point",
               "coordinates": [102.0, 0.5]
           },
           "properties": {
               "prop0": "value0"
           }
       }, {
           "type": "Feature",
           "geometry": {
               "type": "LineString",
               "coordinates": [
                   [102.0, 0.0],
                   [103.0, 1.0],
                   [104.0, 0.0],
                   [105.0, 1.0]
               ]
           },
           "properties": {

The code

Let’s assume you are building a members directory and you have the location of the members as coordinate pair of latitude and longitude. To visualize your members on a map you’ll require the data to be delivered to your map rendering code as GeoJson data.

In this code snippet I’ll only show the code that you need to generate the geojson. In real world you’d have the members data in a database, and do some querys to fetch it for transformation before delivering it via an API/Servlet.

In this article we’ll focus o the transformation to Geojson, you can then figure ot how to wire it to your Rest endpoint, Servlet or any other service requesting the data.

The Member class:

@Data //This is a Lombok annotation, to setup Constractors, Getters, Setters and other stuff for us. Read about it
public class Member implements Serializable {
    private String name;
    private String speciality;
    private double lat; //member latitude
    private double lon; //member longitude
}

Generating dummy data

public static List<Member> members(){
    return new ArrayList<Member>(   ){{
        add(new Member("John Developer","Senior Engineer", 36.783022,-1.289037));
        add(new Member("Uncle Sam","QA Specialist", 36.789177,-1.284348));
        add(new Member("Steve Bob","DBA", 36.784718, -1.282927));
        add(new Member("Donalt Truth","Project Manager", 36.819022, -1.278265));
        add(new Member("Jane West","Health Information System Specialist", 36.817024, -1.299982));
    }};
}

The transformation code. Very simple.

public ObjectNode membersAsGeoJSon() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.writerWithDefaultPrettyPrinter();
            /*"crs": { "type": "name",
                "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" }
            }*/
        ObjectNode featureCollection = mapper.createObjectNode();
        featureCollection.put("type", "FeatureCollection");
        //Start of not mandatory part
       // Only needed if your data is not in CRS84
        ObjectNode crs = mapper.createObjectNode();
        crs.put("type", "name");
        ObjectNode crsProps = mapper.createObjectNode();
        crsProps.put("name", "urn:ogc:def:crs:OGC:1.3:CRS84");
        crs.putPOJO("properties", crsProps);
        featureCollection.putPOJO("crs", crs);
     //End of non mandatory section

        ArrayNode features = mapper.createArrayNode();
        for (Member member : Data.members()) {
            ObjectNode feature = mapper.createObjectNode();
            feature.put("type", "Feature");
            //Geometry Object
            ObjectNode geometryObject = mapper.createObjectNode();
            ArrayNode coordinates = mapper.createArrayNode();
            coordinates.add(member.getLat());
            coordinates.add(member.getLon());
            geometryObject.put("type", "Point");
            geometryObject.putPOJO("coordinates", coordinates);

            //Properties
            ObjectNode properties = mapper.createObjectNode();
            properties.put("name", member.getName());
            properties.put("speciality", member.getSpeciality());

            feature.putPOJO("geometry", geometryObject);
            feature.putPOJO("properties", properties);
            features.addPOJO(feature);
        }
        featureCollection.putPOJO("features", features);
        return featureCollection;
    }

After this you can Write the FeatureCollection ObjectNode as a String using the Jackson JSON ObjectMapper like this.

        ObjectNode output = myService.membersAsGeoJSon();
        ObjectMapper mapper = new ObjectMapper();
        mapper.writerWithDefaultPrettyPrinter();
        String string = mapper.writeValueAsString(output); // This is the GEoJSON String
        System.out.println(string);

Here is the output

{"type":"FeatureCollection","crs":{"type":"name","properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[36.783022,-1.289037]},"properties":{"name":"John Developer","speciality":"Senior Engineer"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[36.789177,-1.284348]},"properties":{"name":"Uncle Sam","speciality":"QA Specialist"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[36.784718,-1.282927]},"properties":{"name":"Steve Bob","speciality":"DBA"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[36.819022,-1.278265]},"properties":{"name":"Donalt Truth","speciality":"Project Manager"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[36.817024,-1.299982]},"properties":{"name":"Jane West","speciality":"Health Information System Specialist"}}]}

You can paste this in any Geojson Viewer and it should display the dummy location.

READ  RASTER DATA: The Python developers; playing ground
Geojson Overlaid in map in Visual Studio Code with Map Preview

You can find the full code on Github repo.

Comment here

Pin It on Pinterest