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:
make contact and location an inner class (same file), but the fields will still not be easily accessed from outside.
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
Convert Word Doc to HTML Programmatically in Java
Can't Start Eclipse - Java Was Started But Returned Exit Code=13
How to Set Httpresponse Timeout For Android in Java
Android 5.0 - Add Header/Footer to a Recyclerview
What's the Difference Between JavaScript and Java
Loop Doesn't See Value Changed by Other Thread Without a Print Statement
Integer Division: How to Produce a Double
Difference Between a Variable, Object, and Reference
How to Get a File'S Media Type (Mime Type)
Example Images For Code and Mark-Up Q&As
Gson Throwing "Expected Begin_Object But Was Begin_Array"
Working Post Multipart Request With Volley and Without Httpentity
How to Ping External Ip from Java Android
Selenium: How to Stop Geckodriver Process Impacting Pc Memory, Without Calling Driver.Quit()
Sort Arraylist of Custom Objects by Property
How to Add Local Jar Files to a Maven Project
Element Myelement Is Not Clickable At Point (X, Y)... Other Element Would Receive the Click