2

I'm having difficulty trying to parse this JSON response into a list of "properties" elements. My JSON looks like this:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "properties": {
                "mag": 6.6,
                "place": "192km ESE of Tadine, New Caledonia"
            }
        },
        {
            "type": "Feature",
            "properties": {
                "mag": 7.5,
                "place": "168km ESE of Tadine, New Caledonia"
            }
        },
        {
            "type": "Feature",
            "properties": {
                "mag": 6,
                "place": "155km ESE of Tadine, New Caledonia"
            }
        }
    ]
}

This is response contains Earthquake details so basically each "properties" within "features" is the POJO I want, but all of them just in a List. Here is my Earthquake class:

public class Earthquake {
    @SerializedName("mag")
    private double magnitude;
    @SerializedName("place")
    private String location;

    public   Earthquake(double magnitude, String location) {
        this.magnitude = magnitude;
        this.location = location;
    }
    // getters
}

I've tried doing custom deserialization suggested here. It gives me the error

Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

suggesting that I'm trying to parse a JsonObject instead of a JsonArray. Here is the deserializer I used.

public class EarthquakeDeserializer implements JsonDeserializer<ArrayList<Earthquake>> {

    @Override
    public ArrayList<Earthquake> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        // get list of "features"
        JsonElement features = json.getAsJsonObject().get("features");

        JsonArray earthquakeElements = new JsonArray();
        for (JsonElement feature : features.getAsJsonArray()){
            JsonElement properties = feature.getAsJsonObject().get("properties");
            earthquakeElements.add(properties);
        }

        Type listType = new TypeToken<ArrayList<Earthquake>>(){}.getType();

        return new Gson().fromJson(earthquakeElements, listType);
    }
}

Any ideas as to what's going on here?

Jaymin
  • 2,879
  • 3
  • 19
  • 35
Donovan Keating
  • 1,715
  • 3
  • 17
  • 27

2 Answers2

1

you can create this kind of a POJO class for your Json, No matter if you want just single part of your response body, you need to create POJO for whole response and from that POJO you need to get appropriate attributes. ->

This is your main json object ->

public class Example {

    @SerializedName("type")
    @Expose
    private String type;
    @SerializedName("features")
    @Expose
    private List<Feature> features = null;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public List<Feature> getFeatures() {
        return features;
    }

    public void setFeatures(List<Feature> features) {
        this.features = features;
    }

}

this is your feature class ->

package com.example;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Feature {

    @SerializedName("type")
    @Expose
    private String type;
    @SerializedName("properties")
    @Expose
    private Properties properties;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

}

this is your properties class ->

package com.example;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Properties {

    @SerializedName("mag")
    @Expose
    private Integer mag;
    @SerializedName("place")
    @Expose
    private String place;

    public Integer getMag() {
        return mag;
    }

    public void setMag(Integer mag) {
        this.mag = mag;
    }

    public String getPlace() {
        return place;
    }

    public void setPlace(String place) {
        this.place = place;
    }

}

After creating this classes, you can serialize the JSON to POJO via GSON library, you can refer to HussainAbbas's answer for how to do it.

Now you can get anything via creating object of response class, and via that object you can access any property you want. Thanks.

Jay Dangar
  • 3,271
  • 1
  • 16
  • 35
  • 1
    I was perhaps wondering if I can avoid creating too many classes. Deep-nested JSON must be tedious to use Retrofit for then. – Donovan Keating Dec 07 '18 at 08:18
  • you can from going root object to the object you like. – Jay Dangar Dec 07 '18 at 08:19
  • 2
    Also, you can automate this task of creating POJO classes from Json via http://www.jsonschema2pojo.org/ this website and there are plugins as well if you are using android studio, eclipse, Intellij Ide. that can generate the POJO classes for you from JSON. so you don't need to create POJO classes as well. the classes that you are looking that i have generated are from jsonschema2pojo website only. so it's not as tadeous as you think it is. :) – Jay Dangar Dec 07 '18 at 08:22
  • Woah. Didn't know they existed! Thanks a bunch! – Donovan Keating Dec 07 '18 at 08:28
  • Do you suggest I create separate files for each class or keep all related classes in one java file? – Donovan Keating Dec 07 '18 at 08:35
  • 1
    Create a package called POJO and create different java POJO classes in them. – Jay Dangar Dec 07 '18 at 08:35
0

check this out

package com.example;

import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Example {

@SerializedName("type")
@Expose
private String type;
@SerializedName("features")
@Expose
private List<Feature> features = null;

  public String getType() {
    return type;
  }

  public void setType(String type) { 
    this.type = type;
  }

  public List<Feature> getFeatures() {
    return features;
  }

  public void setFeatures(List<Feature> features) {
   this.features = features;
  }

}

-----------------------------------com.example.Feature.java-----------------------------------

package com.example;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Feature {

 @SerializedName("type")
 @Expose
 private String type;
 @SerializedName("properties")
 @Expose
 private Properties properties;

 public String getType() { 
   return type;
 }

 public void setType(String type) {
   this.type = type;
 }

 public Properties getProperties() {
   return properties;
 }

 public void setProperties(Properties properties) {
   this.properties = properties; 
 }

} -----------------------------------com.example.Properties.java-----------------------------------

package com.example;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Properties {

   @SerializedName("mag")
   @Expose
   private Integer mag;
   @SerializedName("place")
   @Expose
   private String place;

   public Integer getMag() {
       return mag;
   }

   public void setMag(Integer mag) {
      this.mag = mag;
   } 

   public String getPlace() {
     return place;
   }

   public void setPlace(String place) {
     this.place = place;
   }

 }

After this add this... in your retrofit response

Gson gson = new Gson()
String data = gson.toJson(response.body());
LoginResponse loginResponse = gson.fromJson(dataString,LoginResponse.class);
Example example = gson.fromJson(dataString,Example.class);
String feature_proprerties_mag = example.getFeatures().getProperties().getMag
HussainAbbas
  • 242
  • 2
  • 13