Map GeoJSON to Java with Jackson

Dominika :

I am trying to map a JSON file into Java objects using Jackson library. This json file is a multi-level file that can be found here:

https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson

It is the list of earthquakes that happened in the last 30 days in the US.

Here is the structure of this son file: https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php

Now, I wrote a Java program that is reading fields from this file, specifically I am trying to access the field which is under features -> properties -> place (e.g. from the original file "place":"17km NW of Pinnacles, CA")). When I get to the properties field I can read it as a LinkedHashMap, but the next level, so the keys and values of this LinkedHashMap are being read as Strings:

for example this is one of the values : {type=Point, coordinates=[-121.2743333, 36.6375, 8.61]}

I WANT TO READ THESE VALUES AS ANOTHER OBJECT (NOT STRING, MAP MAYBE?) SO I COULD EXTRACT FURTHER DATA FROM IT.

Here is my class:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.ObjectMapper;

@JsonIgnoreProperties(ignoreUnknown = true)
public class ReadJSONFile {

    private StringBuffer stringBuffer = new StringBuffer();

public void convert_json_to_java() throws Exception {

    String url = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson";
    URL obj = new URL(url);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
    BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
    String inputLine;

        while ((inputLine = in .readLine()) != null) {
                stringBuffer.append(inputLine);
                stringBuffer.append("\n");
        } in.close();
}

@SuppressWarnings("unchecked")
public void map_to_object() throws Exception {

    ObjectMapper om = new ObjectMapper();

    //ignore fields that are not formatted properly
    om.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    Map<Object, Object> resultMap = om.readValue(stringBuffer.toString(), Map.class);
    ArrayList<Object> featuresArrayList = (ArrayList<Object>) resultMap.get("features");

    for(Object o : featuresArrayList) {
        LinkedHashMap<Object, Object> propertiesMap = (LinkedHashMap<Object, Object>) o;
        for(Map.Entry<Object, Object> entry : propertiesMap.entrySet()) {

            //HERE IS THE PROBLEM, THE VALUES OF THIS MAP (SECOND OBJECT) IS BEING READ AS A STRING
            //WHILE SOME VALUES ARE NOT A STRING:
            //e.g. {type=Point, coordinates=[-121.2743333, 36.6375, 8.61]}
            //AND I WANT TO READ IT AS A MAP OR ANY OTHER OBJECT THAT WOULD ALLOW ME TO ACCESS THE DATA
            String propertiesMapValues = entry.getValue().toString();
            }
        }
    }
}

Main.java

public class Main {
    public static void main(String[] args) throws Exception {       
        ReadJSONFile rjf = new ReadJSONFile();
        rjf.convert_json_to_java();
        rjf.map_to_object();
    }
}

Maven dependency: https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-mapper-asl

When I try casting this last object to anything else than String, the program gives me exception (can't cast String to another object). Did I do something wrong? Can someone tell me what can I do to access those fields without modifying Strings (e.g. splitting them into arrays etc.)?

Mafor :

Actually your code works but it could be a bit simplified. The method convert_json_to_java is unnecessary, you can pass the URL directly to the ObjectMapper.

The values in the map are not read as Strings, but you are converting them to Strings by calling toString(), which is defined for all objects. Acctual types can be Map, List, String, Integer etc., depending on the JSON content. Working with a generic map is indeed a bit annoying, so I would suggest you converting values to structured objects. GeoJSON is an open standard, so there are open-source libraries facilitating using it, e.g. geojson-jackson.

You would need to add a maven dependency:

<dependency>
    <groupId>de.grundid.opendatalab</groupId>
    <artifactId>geojson-jackson</artifactId>
    <version>1.8.1</version>
</dependency>

Then the program could look something like:

import org.geojson.*

// ...

public class ReadJSONFile {

    ObjectMapper om = new ObjectMapper();

    public void mapToObject(String url) throws Exception {

        Map<String, Object> resultMap = om.readValue(new URL(url), new TypeReference<Map<String, Object>>() {});
        List<Feature> features = om.convertValue(resultMap.get("features"), new TypeReference<List<Feature>>() {});

        for(Feature f : features) {
            // Write the feature to the console to see how it looks like
            System.out.println(om.writeValueAsString(f));
            // Extract properties
            Map<String,Object> properties = f.getProperties();
            // ....
            // Extract geometry
            GeoJsonObject geometry = f.getGeometry();
            if(geometry instanceof Point) {
                Point p = (Point) geometry;
                // do something with the point
            }  else if(geometry instanceof LineString) {
                LineString mls = (LineString) geometry;
                // ...
            } else if(geometry instanceof MultiLineString) {
                MultiLineString mls = (MultiLineString) geometry;
                // ...
            } else if(geometry instanceof MultiPoint) {
                MultiPoint mp = (MultiPoint) geometry;
                // ...
            } else if(geometry instanceof Polygon) {
                Polygon pl = (Polygon) geometry;
                // ...
            } else if(geometry != null) {
                throw new RuntimeException("Unhandled geometry type: " + geometry.getClass().getName());
            }
        }
    }

    public static void main(String[] args) throws Exception {
        ReadJSONFile rjf = new ReadJSONFile();
        rjf.mapToObject("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson");
    }
}        

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=357526&siteId=1