Get Nested Json Object With Gson Using Retrofit

Get nested JSON object with GSON using retrofit

You would write a custom deserializer that returns the embedded object.

Let's say your JSON is:

{
"status":"OK",
"reason":"some reason",
"content" :
{
"foo": 123,
"bar": "some value"
}
}

You'd then have a Content POJO:

class Content
{
public int foo;
public String bar;
}

Then you write a deserializer:

class MyDeserializer implements JsonDeserializer<Content>
{
@Override
public Content deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException
{
// Get the "content" element from the parsed JSON
JsonElement content = je.getAsJsonObject().get("content");

// Deserialize it. You use a new instance of Gson to avoid infinite recursion
// to this deserializer
return new Gson().fromJson(content, Content.class);

}
}

Now if you construct a Gson with GsonBuilder and register the deserializer:

Gson gson = 
new GsonBuilder()
.registerTypeAdapter(Content.class, new MyDeserializer())
.create();

You can deserialize your JSON straight to your Content:

Content c = gson.fromJson(myJson, Content.class);

Edit to add from comments:

If you have different types of messages but they all have the "content" field, you can make the Deserializer generic by doing:

class MyDeserializer<T> implements JsonDeserializer<T>
{
@Override
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException
{
// Get the "content" element from the parsed JSON
JsonElement content = je.getAsJsonObject().get("content");

// Deserialize it. You use a new instance of Gson to avoid infinite recursion
// to this deserializer
return new Gson().fromJson(content, type);

}
}

You just have to register an instance for each of your types:

Gson gson = 
new GsonBuilder()
.registerTypeAdapter(Content.class, new MyDeserializer<Content>())
.registerTypeAdapter(DiffContent.class, new MyDeserializer<DiffContent>())
.create();

When you call .fromJson() the type is carried into the deserializer, so it should then work for all your types.

And finally when creating a Retrofit instance:

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();

How to get nested JSON object and array from retrofit response on Android?

create a post class and call it from the user class

class userPost {
@SerializedName("id")
private var mId: Int? = null

@SerializedName("link")
private var mLink: ArrayList<String>? = null

fun getId(): Int {
return mId!!
}

fun setId(id: Int) {
mId = id
}

fun getLink(): ArrayList<String> {
return mLink!!
}

fun setLink(link: ArrayList<String>) {
mLink= link
}

}

And on the user class add

@SerializedName("post")
private var mPost: userPost? = null

fun getPost(): userPost? {
return mPost
}

fun setPost(post: userPost) {
mPost = post
}

How to get data from nested JSON objects using Gson

The entire JSON response can be read as a JSONObject that has multiple elements in it that you can iterate through and get different data.

String jsonResponse = ""; // Put the entire JSON response as a String 
JSONObject root = new JSONObject(jsonResponse);

JSONArray rootArray = root.getJSONArray("countries"); // root element of the json respons

for (int i = 0; i < rootArray.length(); i++) {

JSONObject number = rootArray.getJSONObject(i);
String country = number.getString("name"); // Get country name

// Here you can add `country` into a List
}

UPDATE:

but there is no array in my JSON file, all of them are objects, every
country is in an object and every object has its own SerializedName

You can read it into JSONOjbect, and instead of using a JSONArray, you can iterate over the length of the JSONObject as below.

try {
JSONObject root = new JSONObject(jsonResponse);
JSONObject countries = root.getJSONObject("countries");

for (int i = 1; i <= countries.length(); i++) {

JSONObject number = countries.getJSONObject(String.valueOf(i));
String country = number.getString("name"); // Get country name

// Here you can add the `country` into a List
}

} catch (JSONException e) {
e.printStackTrace();
}

how to retrieve nested json object with retrofit?

Two ways:

  1. make contact and location an inner class (same file), but the fields will still not be easily accessed from outside.

  2. you can instead create a method to access the attributes in contacts from Address.

I use http://www.jsonschema2pojo.org/ to auto generate the files below

public class Address {

// create a method here to get first/last name
public String getFirstName(){
return primaryContact==null? "" :
primaryContact.getFirstName();
}
// do the same for which ever inner attributes you like to access.

@SerializedName("name")
@Expose
private String name;
@SerializedName("address")
@Expose
private String address;
@SerializedName("location")
@Expose
private Location location;
@SerializedName("email")
@Expose
private String email;
@SerializedName("primaryContact")
@Expose
private PrimaryContact primaryContact;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public Location getLocation() {
return location;
}

public void setLocation(Location location) {
this.location = location;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public PrimaryContact getPrimaryContact() {
return primaryContact;
}

public void setPrimaryContact(PrimaryContact primaryContact) {
this.primaryContact = primaryContact;
}

}
-----------------------------------com.example.Location.java-----------------------------------

package com.example;

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

public class Location {

@SerializedName("lon")
@Expose
private Double lon;
@SerializedName("lat")
@Expose
private Double lat;

public Double getLon() {
return lon;
}

public void setLon(Double lon) {
this.lon = lon;
}

public Double getLat() {
return lat;
}

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

}
-----------------------------------com.example.PrimaryContact.java-----------------------------------

package com.example;

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

public class PrimaryContact {

@SerializedName("firstName")
@Expose
private String firstName;
@SerializedName("lastName")
@Expose
private String lastName;
@SerializedName("jobTitle")
@Expose
private String jobTitle;
@SerializedName("email")
@Expose
private String email;
@SerializedName("photo")
@Expose
private String photo;

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getJobTitle() {
return jobTitle;
}

public void setJobTitle(String jobTitle) {
this.jobTitle = jobTitle;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getPhoto() {
return photo;
}

public void setPhoto(String photo) {
this.photo = photo;
}

}

How do I parse a field from a deep nested json object using Gson and retrofit in android?

I use this : http://www.jsonschema2pojo.org/ to generate a class from
the above json string. I was wondering how do I retrieve the
"started_at": "2019-06-07T19:00:00-0400",
from busyAt-> events into my main model class generated by the above
site? Say at the same level as mySpaceId. I currently use the
following :

If I interpret you correctly, you have created using the www.jsonschema2pojo.org the following classes: -

  • a class called "Entity" that contains "mySpaceId" and a list of "BusyAt".
  • class "BusyAt" contains a list of "Event".
  • class "Event" contain a String called StartedAt.

I assume that you want to retrieve the First entry of each list (if it exist) directly from the top-most class ("Entity")

something like: -

entity.busyAt(0).events(0).startedAt

if either busyAt or event list is empty or null, then return empty string for startedAt.

what you can do, is to create the following method in the "Entity" class (root class containing both mySpaceId, and List).

public String getStartedAt(){
//check if the busyAt List contains items or not.
if (busyAt ==null || busyAt.isEmpty()){
return "";
}
//take the list of events from the first busyAt in the array
List<Event> eventList = busyAt.get(0).getEvents();
//check if the event List contains items or not.
if (eventList ==null || eventList.isEmpty()){
return "";
}
//return the StartAt value of the first event.
return eventList.get(0).getStartedAt();
}

How can Retrofit 2.0 parse nested JSON object?

Assuming your complete JSON looks like

{
"title": "Recent Uploads tagged android",
"link": "https://www.flickr.com/photos/tags/android/",
"description": "",
"modified": "2015-10-05T05:30:01Z",
"generator": "https://www.flickr.com/",
"items": [
{
"member1": "memeber value",
"member2": "member value"
},
{
"member1": "memeber value",
"member2": "member value"
}
]
}

So Pojo classes would be

public class MainPojo {
private String title;
private String description;
private String link;
private String generator;
private String modified;
private ArrayList<Items> items;

// Getters setters
}

public class Items {
private String member2;
private String member1;

// Getters setters
}

Note : This is similar solution for your JSON. Members of Items.java can be changed if JSON has other keys.


Update for Pojo as new JSON

public class Items {
private String tags;
private String author;
private String title;
private String description;
private String link;
private String author_id;
private String published;
private Media media;

// Getters and Setters
}

public class Media {
private String m;
// Getters and Setters
}

retrofit 2.3.0 how to handle nested json?

the http://www.jsonschema2pojo.org/ to convert your json to POJO and use that for retrofit 2.3

How to parse Nested json using Retrofit ....?

CurrentObservation.class

public class CurrentObservation {

@SerializedName("image")
@Expose
private Image1 image;

public Image1 getImage() {
return image;
}

public void setImage(Image1 image) {
this.image = image;
}
}

Example.java

public class Example {

@SerializedName("current_observation")
@Expose
private CurrentObservation currentObservation;

public CurrentObservation getCurrentObservation() {
return currentObservation;
}

public void setCurrentObservation(CurrentObservation currentObservation) {
this.currentObservation = currentObservation;
}
}

Image1.java

public class Image1 {

@SerializedName("url")
@Expose
private String url;
@SerializedName("title")
@Expose
private String title;
@SerializedName("link")
@Expose
private String link;

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getLink() {
return link;
}

public void setLink(String link) {
this.link = link;
}

}

To call it in main Activity

  Call<Example> ex = BaseUrlClass.getInterface().ex("whatever parameters");
ex.enqueue(new Callback<Example>() {
@Override
public void onResponse(Call<Example> call, Response<Example> response) {
Example list = response.body();

CurrentObservation a = list.getCurrentObservation();
List<Image1> im = a.getImage();
for (int i = 0;i<im.size();i++){
Image1 image1= im.get(i);
String a = image1.getTitle();
String b = image1.getUrl();
String c = image1.getLink();
}
}

@Override
public void onFailure(Call<Example> call, Throwable t) {

}
});

Lastly in your Interface

public interface ApiUtils {

@GET("") //whatever url
Call<Example> ex(); //or any parameter
}


Related Topics



Leave a reply



Submit