How can I parse GeoJson with Gson? - java

I want to write an app that will load GeoJson using Gson as the only dependency. Using Gson is pretty pedestrian but when it comes to the anonymous arrays for the coordinates I am at a loss. The 'coordinates' array is an array of arrays. AAARRRGGG!
"geometry":{
"type":"Polygon",
"coordinates":[
[
[
-69.899139,
12.452005
],
[
-69.895676,
12.423015
],
I can load all the other data but the 'coordinates' arrays do not have names, so how do I load them up?
I have tried several iterations of this but no joy...
public static final class Coordinate {
public final double[] coord;
public Coordinate(double[] coord) {
this.coord = coord;
}
}
Any help? I know there are already packages that parse geojson but I would like to understand the JSON loading. And what are unnamed arrays called? Anonymous arrays does not google well!

You can get Gson to parse triply-nested-nameless arrays by declaring the coordinate field as a double[][][].
Here's a runnable sample program that demonstrates how to do it:
import org.apache.commons.lang3.ArrayUtils;
import com.google.gson.Gson;
public class Scratch {
public static void main(String[] args) throws Exception {
String json = "{" +
" \"geometry\": {" +
" \"type\": \"Polygon\"," +
" \"coordinates\": [" +
" [" +
" [-69.899139," +
" 12.452005" +
" ]," +
" [-69.895676," +
" 12.423015" +
" ]" +
" ]" +
" ]" +
" }" +
"}";
Geometry g = new Gson().fromJson(json, Geometry.class);
System.out.println(g);
// Geometry [geometry=GeometryData [type=Polygon, coordinates={{{-69.899139,12.452005},{-69.895676,12.423015}}}]]
}
}
class Geometry {
GeometryData geometry;
#Override
public String toString() {
return "Geometry [geometry=" + geometry + "]";
}
}
class GeometryData {
String type;
double[][][] coordinates;
#Override
public String toString() {
return "GeometryData [type=" + type + ", coordinates=" + ArrayUtils.toString(coordinates) + "]";
}
}

Related

How to put a JsonElement back into a JsonObject?

The goal is replace a value in a nested JSON.
Original JSON :
{
"data": {
"car": {
"xia": [
"a0.c904.b0"
]
}
}
}
Expected JSON:
{
"data": {
"car": {
"xia": [
"a0.c234.b0"
]
}
}
}
My code below gives me the JSONElement but I don't know how to put it back to the json object?
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
String inputJson = "{\n"
+ " \"data\": {\n"
+ " \"car\": {\n"
+ " \"xia\": [\n"
+ " \"a0.c904.b0\"\n"
+ " ]\n"
+ " }\n"
+ " }\n"
+ "}";
JsonObject jsonObject = new JsonParser().parse(inputJson).getAsJsonObject();
JsonElement jsonElement = jsonObject.get("data").getAsJsonObject().get("car").getAsJsonObject().get("xia");
String str = jsonElement.getAsString();
System.out.println(str);
String[] strs = str.split("\\.");
String replaced = strs[0] + "." + strs[1].replaceAll("\\d+", "234") + "." + strs[2];
System.out.println(replaced);
JsonElement jsonElementReplaced = new JsonParser().parse(replaced);
I just had to do :
jsonObject.get("data").getAsJsonObject().get("car").getAsJsonObject().add("xia", jsonElementReplaced);

Return string in valid JSON

I want to return valid json string.
Ex:
{
"status":"Success",
"total_amt": "41",
"igst_amt": 14,
"sgst_amt": 0,
"cgst_amt": "12",
"cess_amt": 15
}
Expected:
{
"status":"Success",
"total_amt": "41",
"igst_amt": "14",
"sgst_amt": "0",
"cgst_amt": "12",
"cess_amt": "15"
}
I have wrote below code:
public String toString() {
return "{\"status\":\"" + status + "\",\"total_amt\":\"" + total_amt + "\",\"igst_amt\":\"" + igst_amt
+ "\",\"sgst_amt\":\"" + sgst_amt + "\",\"cgst_amt:\"" + cgst_amt + "\",\"cess_amt\":\"" + cess_amt + "\"}";
}
It is not returning valid JSON.
You can use a third party lib. This example uses GSON
class Result {
private String status;
#SerializedName("total_amt")
private int totalAmount;
#SerializedName("igst_amt")
private int igstAmount;
#SerializedName("sgst_amt")
private int sgstAmount;
#SerializedName("cgst_amt")
private int cgstAmount;
#SerializedName("cess_amt")
private int cessAmount;
public Result() {}
}
Result result = new Result();
// set your fields
String json = new Gson().toJson(result);
I hope igst_amt, sgst_amt and cess_amt are Integers.
So you add .toString() to them
public String toString() {
return "{\"status\":\"" + status + "\",\"total_amt\":\"" + total_amt + "\",\"igst_amt\":\"" + igst_amt.toString()
+ "\",\"sgst_amt\":\"" + sgst_amt.toString() + "\",\"cgst_amt:\"" + cgst_amt + "\",\"cess_amt\":\"" + cess_amt.toString() + "\"}";
}
Read about gson for returning json format. link to gson github
To simple use it you can:
final Gson gson = new GsonBuilder().setPrettyPrinting().create();
final String string = "you string";
return gson.toJson(string);

JSON array elements to ArrayList for JSP

I am trying to add specific values from the following JSON to a Java ArrayList. I would then like to use this ArrayList within a JSP. This is the JSON:
{
"page": 1,
"rpp": 3,
"total": 3294,
"request_time": "2018-04-23T16:10:20+01:00",
"stops": [
{
"atcocode": "370023715",
"longitude": -1.46616,
"latitude": 53.38248,
"distance": 57
},
{
"atcocode": "370027281",
"longitude": -1.46583,
"latitude": 53.38228,
"distance": 77
},
{
"atcocode": "370022803",
"longitude": -1.46616,
"latitude": 53.38227,
"distance": 80
}
]
}
I would like to add each longitude and latitude elements from under the "stops" subtree into 2 different ArrayLists. This is my attempted code for that:
public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{
try {
String json = readUrl (link);
JsonParser parser = new JsonParser();
JsonElement element = parser . parse (json);
if (element.isJsonObject()) {
JsonObject bus = element . getAsJsonObject ();
JsonArray array = bus . getAsJsonArray ("stops");
for (int i = 0; i < array.size(); i++) {
List<String> longitudes = new ArrayList<String>();
List<String> latitudes = new ArrayList<String>();
longitudes.add(array.get(i)).get("longitude");
latitudes.add(array.get(i)).get("latitude");
request.setAttribute("longitudes", longitudes);
request.setAttribute("latitudes", latitudes);
RequestDispatcher dispatcher = request . getRequestDispatcher ("latlong.jsp");
dispatcher.forward(request, response);
}
}
}
}
i get the following error of: "error: incompatible types: JsonElement cannot be converted to String"
Thank you in advance!
One other error you have is that the longitudes, latitudes lists are inside of the loop.
Here is a simple testable piece of code which extracts the data from the JSON and can be tested locally. You can adapt it to your purposes ...
public static void main(String[] args) {
String json = "{\n" +
"\"page\": 1,\n" +
"\"rpp\": 3,\n" +
"\"total\": 3294,\n" +
"\"request_time\": \"2018-04-23T16:10:20+01:00\",\n" +
"\"stops\": [\n" +
"{\n" +
" \"atcocode\": \"370023715\",\n" +
" \"longitude\": -1.46616,\n" +
" \"latitude\": 53.38248,\n" +
" \"distance\": 57\n" +
"},\n" +
"{\n" +
" \"atcocode\": \"370027281\", \n" +
" \"longitude\": -1.46583,\n" +
" \"latitude\": 53.38228,\n" +
" \"distance\": 77\n" +
"},\n" +
"{\n" +
" \"atcocode\": \"370022803\",\n" +
" \"longitude\": -1.46616,\n" +
" \"latitude\": 53.38227,\n" +
" \"distance\": 80\n" +
" }\n" +
"]\n" +
"}";
JsonParser jsonParser = new JsonParser();
JsonElement element = jsonParser.parse(json);
List<String> longitudes = new ArrayList<>();
List<String> latitudes = new ArrayList<>();
if (element.isJsonObject()) {
JsonObject bus = element . getAsJsonObject ();
JsonArray array = bus.getAsJsonArray("stops");
array.forEach(jsonElement -> {
extractToList(longitudes, (JsonObject) jsonElement, "longitude");
extractToList(latitudes, (JsonObject) jsonElement, "latitude");
});
}
System.out.println(longitudes);
System.out.println(latitudes);
}
private static void extractToList(List<String> list, JsonObject jsonElement, String field) {
final JsonElement longitude = jsonElement.get(field);
if(longitude != null) {
list.add(longitude.getAsString());
}
}
If you run this you get printed out on the console:
[-1.46616, -1.46583, -1.46616]
[53.38248, 53.38228, 53.38227]
I have assumed you are using Google's GSON library.
Instead of
longitudes.add(array.get(i)).get("longitude");
latitudes.add(array.get(i)).get("latitude");
Use
longitudes.add(array.get(i).get("longitude").getAsString());
latitudes.add(array.get(i).get("latitude").getAsString());

How to parse json string created by stringify function in javascript?

I want to parse the json string in java class (.java) created by stringify() function in javascript. I know to parse the string like:
String JSON_DATA
= "{"
+ " \"geodata\": ["
+ " {"
+ " \"id\": \"1\","
+ " \"name\": \"Julie Sherman\","
+ " \"gender\" : \"female\","
+ " \"latitude\" : \"37.33774833333334\","
+ " \"longitude\" : \"-121.88670166666667\""
+ " },"
+ " {"
+ " \"id\": \"2\","
+ " \"name\": \"Johnny Depp\","
+ " \"gender\" : \"male\","
+ " \"latitude\" : \"37.336453\","
+ " \"longitude\" : \"-121.884985\""
+ " }"
+ " ]"
+ "}";
but how to parse this string?
var IO = {
//returns array with storable google.maps.Overlay-definitions
IN: function(arr, //array with google.maps.Overlays
encoded//boolean indicating whether pathes should be stored encoded
) {
var shapes = [],
goo = google.maps,
shape, tmp;
for (var i = 0; i < arr.length; i++)
{
shape = arr[i];
tmp = {type: this.t_(shape.type), id: shape.id || null};
switch (tmp.type) {
case 'CIRCLE':
tmp.radius = shape.getRadius();
tmp.geometry = this.p_(shape.getCenter());
break;
case 'MARKER':
tmp.geometry = this.p_(shape.getPosition());
break;
case 'RECTANGLE':
tmp.geometry = this.b_(shape.getBounds());
break;
case 'POLYLINE':
tmp.geometry = this.l_(shape.getPath(), encoded);
break;
case 'POLYGON':
tmp.geometry = this.m_(shape.getPaths(), encoded);
break;
}
shapes.push(tmp);
}
return shapes;
}
and the string formed to be parsed is:
[{"type":"CIRCLE","id":null,"radius":1730.4622192451884,"geometry":[32.3610810916614,50.91339111328125]},{"type":"CIRCLE","id":null,"radius":1831.5495077322266,"geometry":[32.35528086804335,50.997161865234375]},{"type":"CIRCLE","id":null,"radius":1612.2461023303567,"geometry":[32.34454947365649,51.011924743652344]}]
You can use Gson or Jackson for this. Create a POJO that hold the data and use these libs. An eg with Gson
import java.lang.reflect.Type;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
class JsonData {
private String type;
private String id;
private double radius;
private List<Double> geometry;
//Getters & Setters
}
public class JsonParser {
public static void main(String[] args) {
String json = "[{\"type\":\"CIRCLE\",\"id\":null,\"radius\":1730.4622192451884,\"geometry\":[32.3610810916614,50.91339111328125]},{\"type\":\"CIRCLE\",\"id\":null,\"radius\":1831.5495077322266,\"geometry\":[32.35528086804335,50.997161865234375]},{\"type\":\"CIRCLE\",\"id\":null,\"radius\":1612.2461023303567,\"geometry\":[32.34454947365649,51.011924743652344]}]";
Type listType = new TypeToken<List<JsonData>>() {}.getType();
List<JsonData> disputeSummaryArraylistobjectList = new Gson().fromJson(json, listType);
System.out.println(disputeSummaryArraylistobjectList);
}
}
You will need a JSON parser for Java like GSON or Jackson.
There are two strategies for parsing:
Creating Java objects and let the JSON parsers map elements in the input to fields
Iterating over the generic JSON data structure which the parser returns
The documentation of both projects contain lots of examples how to achieve either.

GSON fromJSON Deserialization with Conditional to Exclude Specific Object Instances

Given the following JSON response:
{
"status": "OK",
"regions": [
{
"id": "69",
"name": "North Carolina Coast",
"color": "#01162c",
"hasResorts": 1
},
{
"id": "242",
"name": "North Carolina Inland",
"color": "#01162c",
"hasResorts": 0
},
{
"id": "17",
"name": "North Carolina Mountains",
"color": "#01162c",
"hasResorts": 1
},
{
"id": "126",
"name": "Outer Banks",
"color": "#01162c",
"hasResorts": 1
}
]
}
I'm trying to create a List of Region objects. Here's a very abridged version of my current code:
JSONObject jsonObject = new JSONObject(response);
String regionsString = jsonObject.getString("regions");
Type listType = new TypeToken<ArrayList<Region>>() {}.getType();
List<Region> regions = new Gson().fromJson(regionsString, listType);
This is all working fine. However, I'd like to exclude the regions in the final List that hasResorts == 0. I realize I can loop through the actual JSONObjects and check them before calling fromJSON on each region. But I'm assuming there is a GSON specific way of doing this.
I was looking at the ExclusionStrategy(). Is there a simple way to implement this to JSON deserialization?
ExclusionStrategy won't help you since it works without the context of deserialization. Indeed, you can exclude only a specific kind of class. I think that best way of doing it is through custom deserialization. Here is what I mean (you can copy&paste&try immediately):
package stackoverflow.questions.q19912055;
import java.lang.reflect.Type;
import java.util.*;
import stackoverflow.questions.q17853533.*;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
public class Q19912055 {
class Region {
String id;
String name;
String color;
Integer hasResorts;
#Override
public String toString() {
return "Region [id=" + id + ", name=" + name + ", color=" + color
+ ", hasResorts=" + hasResorts + "]";
}
}
static class RegionDeserializer implements JsonDeserializer<List<Region>> {
public List<Region> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
if (json == null)
return null;
ArrayList<Region> al = new ArrayList<Region>();
for (JsonElement e : json.getAsJsonArray()) {
boolean deserialize = e.getAsJsonObject().get("hasResorts")
.getAsInt() > 0;
if (deserialize)
al.add((Region) context.deserialize(e, Region.class));
}
return al;
}
}
/**
* #param args
*/
public static void main(String[] args) {
String json =
" [ "+
" { "+
" \"id\": \"69\", "+
" \"name\": \"North Carolina Coast\", "+
" \"color\": \"#01162c\", "+
" \"hasResorts\": 1 "+
" }, "+
" { "+
" \"id\": \"242\", "+
" \"name\": \"North Carolina Inland\", "+
" \"color\": \"#01162c\", "+
" \"hasResorts\": 0 "+
" }, "+
" { "+
" \"id\": \"17\", "+
" \"name\": \"North Carolina Mountains\", "+
" \"color\": \"#01162c\", "+
" \"hasResorts\": 1 "+
" }, "+
" { "+
" \"id\": \"126\", "+
" \"name\": \"Outer Banks\", "+
" \"color\": \"#01162c\", "+
" \"hasResorts\": 1 "+
" } "+
" ] ";
Type listType = new TypeToken<ArrayList<Region>>() {}.getType();
List<Region> allRegions = new Gson().fromJson(json, listType);
System.out.println(allRegions);
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(listType, new RegionDeserializer());
Gson gson2 = builder.create();
List<Region> regionsHaveResort = gson2.fromJson(json, listType);
System.out.println(regionsHaveResort);
}
}

Categories

Resources