How to iterate key-value pair in Retrofit - java

I am having trouble parsing the below JSON structure. Basically I have to read the values object as list but the server returns as a JsonObject and the value changes based on the totalPageCount. Is there any way I can read the values as List? Should I use reflections ? Currently I am using Retrofit with returns the model class.
Any help is really appreciated.
Thank you
{
"page" : 0,
"pageSize" : 10,
"totalPageCount" : 1,
"values" : {
"key1" : "value1",
"key2" : "value2",
"key3" : "value3",
"key4" : "value4",
}
}
Model class :
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Example {
#SerializedName("page")
#Expose
private Integer page;
#SerializedName("pageSize")
#Expose
private Integer pageSize;
#SerializedName("totalPageCount")
#Expose
private Integer totalPageCount;
#SerializedName("values")
#Expose
private Values values;
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getTotalPageCount() {
return totalPageCount;
}
public void setTotalPageCount(Integer totalPageCount) {
this.totalPageCount = totalPageCount;
}
public Values getValues() {
return values;
}
public void setValues(Values values) {
this.values = values;
}
}
-----------------------------------com.example.Values.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Values {
#SerializedName("key1")
#Expose
private String key1;
#SerializedName("key2")
#Expose
private String key2;
#SerializedName("key3")
#Expose
private String key3;
#SerializedName("key4")
#Expose
private String key4;
public String getKey1() {
return key1;
}
public void setKey1(String key1) {
this.key1 = key1;
}
public String getKey2() {
return key2;
}
public void setKey2(String key2) {
this.key2 = key2;
}
public String getKey3() {
return key3;
}
public void setKey3(String key3) {
this.key3 = key3;
}
public String getKey4() {
return key4;
}
public void setKey4(String key4) {
this.key4 = key4;
}
}

This will work
private Map<String,String> values;

Related

How to use Gson fromJson in this situation?

I want to convert json to Java Obejct using Gson.
For example, Json structure is ...
{
"title": "title",
"product" : [
{
"key": "product1",
"value": [{
"valueName": "productValue1"
}]
"date" : "2022-10-11"
},
{
"key": "product2",
"value": []
},
"date" : "2022-10-11"
]
}
I made DTOs like...
public Class ProductDTO {
String title;
List<Product> product;
}
public Class Product {
String key;
List<Value> value;
}
public Class Value {
String valueName;
}
And
// payload: String
Gson gson = new Gson();
ProductDTO productDTO = gson.fromJson(payload, ProductDTO.class);
When executing fromJson, I had MalformedJsonException.
In json, value List size == 0 for "key": "product2"
But I have String valueName attribute in Value Class.
How can I resolve this problem?
I think your model classes will be like that
public class Product {
#SerializedName("key")
#Expose
private String key;
#SerializedName("value")
#Expose
private List<Value> value = null;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public List<Value> getValue() {
return value;
}
public void setValue(List<Value> value) {
this.value = value;
}
}
public class ProductDTO {
#SerializedName("title")
#Expose
private String title;
#SerializedName("product")
#Expose
private List<Product> product = null;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<Product> getProduct() {
return product;
}
public void setProduct(List<Product> product) {
this.product = product;
}
}
public class Value {
#SerializedName("valueName")
#Expose
private String valueName;
public String getValueName() {
return valueName;
}
public void setValueName(String valueName) {
this.valueName = valueName;
}
}

How to parse nested Json Array in retrofit?

The parsing is successful but problem is ,it is taking loggedinClients only,ActiveClients not getting in retrofit , how can we parse array under array and with no object name?
{
"status": 200,
"success": true,
"messages": "",
"result": [
[
{
"LoggedinClients": 1
}
],
[
{
"ActiveClients": 0
}
]
]
}
partly Related Code:
public class OnlineInfoResponse {
#SerializedName("result")
#Expose
private List<List<OnlineInfoLoggedInResult>> lstLists = null;
public List<List<OnlineInfoLoggedInResult>> getLstLoggedIn() {
return lstLists;
}
public void setLstLists(List<List<OnlineInfoLoggedInResult>> lstLists) {
this.lstLists = lstLists;
}
OnlineInfoLoggedInResult.java
public class OnlineInfoLoggedInResult {
#SerializedName("LoggedinClients")
#Expose
private int loggedinClients;
public int getLoggedinClients() {
return loggedinClients;
}
public void setLoggedinClients(int loggedinClients) {
this.loggedinClients = loggedinClients;
}
#SerializedName("ActiveClients")
#Expose
private int activeClients;
public int getActiveClients() {
return activeClients;
}
public void setActiveClients(int activeClients) {
this.activeClients = activeClients;
}
}
this i got parsing from jsonschema.I am having problem in nested jsonarray.
You should generate the following POJO
public class YourPojoName {
private float status;
private boolean success;
private String messages;
List <List< Object> > result = new ArrayList < ArrayList<Object> > ();
// Getter Methods
public float getStatus() {
return status;
}
public boolean getSuccess() {
return success;
}
public String getMessages() {
return messages;
}
// Setter Methods
public void setStatus(float status) {
this.status = status;
}
public void setSuccess(boolean success) {
this.success = success;
}
public void setMessages(String messages) {
this.messages = messages;
}
}
public class abbb {
#Expose
#SerializedName("result")
private List<List<Result>> result;
#Expose
#SerializedName("messages")
private String messages;
#Expose
#SerializedName("success")
private boolean success;
#Expose
#SerializedName("status")
private int status;
public List<List<Result>> getResult() {
return result;
}
public void setResult(List<List<Result>> result) {
this.result = result;
}
public String getMessages() {
return messages;
}
public void setMessages(String messages) {
this.messages = messages;
}
public boolean getSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public static class Result {
#Expose
#SerializedName("LoggedinClients")
private int LoggedinClients;
#Expose
#SerializedName("ActiveClients")
private int active_clients;
//genetrate getter setter
}
}

How do I deserialize a nested JSON array using GSON?

Here's an example of my JSON:
{
"status": "ok",
"rowCount": 60,
"pageCount": 6,
"value": [{
"CustomerID": 1911,
"CustomerTypeID": 3,
...
}
]
}
My POJO:
#SerializedName("CustomerID")
public Integer CustomerID;
#SerializedName("CustomerTypeID")
public Integer CustomerTypeID;
I want to pull everything under value.
How do I do this using Google's GSON?
I've tried doing it as I would normally, but for, obvious reasons, it didn't work:
Type collectionType = new TypeToken<ArrayList<Customer>>() {}.getType();
return gson.fromJson(json, collectionType);
You can not skip root JSON object. The simplest solution in this case is - create root POJO:
class Response {
#SerializedName("value")
private List<Customer> customers;
// getters, setters
}
And you can use it as below:
return gson.fromJson(json, Response.class).getCustomers();
You don't need to worry writing your own POJO.
just visit http://www.jsonschema2pojo.org/
and paste here your JSON data, it'll automatically return you converted classes as below
-----------------------------------com.example.Example.java-----------------------------------
package com.example;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Example {
#SerializedName("status")
#Expose
private String status;
#SerializedName("rowCount")
#Expose
private Integer rowCount;
#SerializedName("pageCount")
#Expose
private Integer pageCount;
#SerializedName("value")
#Expose
private List<Value> value = null;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Integer getRowCount() {
return rowCount;
}
public void setRowCount(Integer rowCount) {
this.rowCount = rowCount;
}
public Integer getPageCount() {
return pageCount;
}
public void setPageCount(Integer pageCount) {
this.pageCount = pageCount;
}
public List<Value> getValue() {
return value;
}
public void setValue(List<Value> value) {
this.value = value;
}
}
-----------------------------------com.example.Value.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Value {
#SerializedName("CustomerID")
#Expose
private Integer customerID;
#SerializedName("CustomerTypeID")
#Expose
private Integer customerTypeID;
public Integer getCustomerID() {
return customerID;
}
public void setCustomerID(Integer customerID) {
this.customerID = customerID;
}
public Integer getCustomerTypeID() {
return customerTypeID;
}
public void setCustomerTypeID(Integer customerTypeID) {
this.customerTypeID = customerTypeID;
}
}
The above two classes are auto generated by website.
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class ExampleClass {
#SerializedName("status")
#Expose
private String status;
#SerializedName("rowCount")
#Expose
private int rowCount;
#SerializedName("pageCount")
#Expose
private int pageCount;
#SerializedName("value")
#Expose
private List<Value> value = null;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public int getRowCount() {
return rowCount;
}
public void setRowCount(int rowCount) {
this.rowCount = rowCount;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public List<Value> getValue() {
return value;
}
public void setValue(List<Value> value) {
this.value = value;
}
}
-----------------------------------Value.java-----------------------------------
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Value {
#SerializedName("CustomerID")
#Expose
private int customerID;
#SerializedName("CustomerTypeID")
#Expose
private int customerTypeID;
public int getCustomerID() {
return customerID;
}
public void setCustomerID(int customerID) {
this.customerID = customerID;
}
public int getCustomerTypeID() {
return customerTypeID;
}
public void setCustomerTypeID(int customerTypeID) {
this.customerTypeID = customerTypeID;
}
}
/********* parsing with Gson ******/
GsonBuilder gsonBuilder = new GsonBuilder();
gson = gsonBuilder.create();
ExampleClass resultObj = gson.fromJson(jsonObject.toString(), ExampleClass.class);
List<Value> yourListOfCustomerValues = resultObj.getValue();
You can refer to this amazing post on mapping of arrays and lists of objects with Gson by Norman Peitek
Basics of Gson, model annotations and mapping of nested objects

Android class structure for json with multiple elements

I have an Android application that gets a json from a http call and looks like this:
{
"string_1":{
"prop_1":"value",
"prop_2":"value"
},
"string_2":{
"prop_1":"value",
"prop_2":"value"
},
...
"string_n":{
"prop_1":"value",
"prop_2":"value"
}
}
Here's the java class I wrote to use the data in my code:
public class FooClass implements Serializable {
private LinkedHashMap<String, FooObject> objectsMap;
public LinkedHashMap<String, FooObject> getObjectsMap() {
return objectsMap;
}
}
where FooObject is:
public class FooObject implements Serializable {
#SerializedName("prop_1")
private String property1;
#SerializedName("prop_2")
private String property2;
public String getProperty1() {
return property1;
}
public String getProperty1() {
return property1;
}
}
But since my json doesn't have an element called "objectsMap" my linked hash map from FooClass is always null.
What class structure should I use for this json structure?
Thank you.
UPDATE:
I have managed to solve my problem. I use retrofit 1.9, and make the method return a result of type LinkedHashMap and it solved my problem.
Better and more feasible is to change your response structure and have an Array rather than string_1, string_2... string_n. If you can't do that you will have to iterate through all the possible keys and save the response something like this
jObject = new JSONObject(response);
Iterator<?> keys = jObject.keys();
while( keys.hasNext() ) {
String key = (String)keys.next();
if ( jObject.get(key) instanceof JSONObject ) {
// do your stuff here
}
}
-----------------------------------com.example.Example.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Example {
#SerializedName("string_1")
#Expose
private String1 string1;
#SerializedName("string_2")
#Expose
private String2 string2;
#SerializedName("string_n")
#Expose
private StringN stringN;
public String1 getString1() {
return string1;
}
public void setString1(String1 string1) {
this.string1 = string1;
}
public String2 getString2() {
return string2;
}
public void setString2(String2 string2) {
this.string2 = string2;
}
public StringN getStringN() {
return stringN;
}
public void setStringN(StringN stringN) {
this.stringN = stringN;
}
}
-----------------------------------com.example.String1.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class String1 {
#SerializedName("prop_1")
#Expose
private String prop1;
#SerializedName("prop_2")
#Expose
private String prop2;
public String getProp1() {
return prop1;
}
public void setProp1(String prop1) {
this.prop1 = prop1;
}
public String getProp2() {
return prop2;
}
public void setProp2(String prop2) {
this.prop2 = prop2;
}
}
-----------------------------------com.example.String2.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class String2 {
#SerializedName("prop_1")
#Expose
private String prop1;
#SerializedName("prop_2")
#Expose
private String prop2;
public String getProp1() {
return prop1;
}
public void setProp1(String prop1) {
this.prop1 = prop1;
}
public String getProp2() {
return prop2;
}
public void setProp2(String prop2) {
this.prop2 = prop2;
}
}
-----------------------------------com.example.StringN.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class StringN {
#SerializedName("prop_1")
#Expose
private String prop1;
#SerializedName("prop_2")
#Expose
private String prop2;
public String getProp1() {
return prop1;
}
public void setProp1(String prop1) {
this.prop1 = prop1;
}
public String getProp2() {
return prop2;
}
public void setProp2(String prop2) {
this.prop2 = prop2;
}
}
Hope it helps and you can use http://www.jsonschema2pojo.org/
If you're using a SerializedName annotation in your Response class which you're trying to map, just delete it and map your Json Response to
public class FooClass implements Serializable {
private Map<String, FooObject> objectsMap;
public Map<String, FooObject> getObjectsMap() {
return objectsMap;
}
}

How to extract array of json inside an attribute of type List from an object

I am using Flickr API to get the information of images and returns the following JSON:
{"photos":{"page":1,"pages":60,"perpage":100,"total":"5964","photo":[{"id":"21577339501","owner":"85277110#N02","secret":"31e850dfeb","server":"5785","farm":6,"title":"P1390956","ispublic":1,"isfriend":0,"isfamily":0}, {"id":"21577287101","owner":"85277110#N02","secret":"412990658f","server":"611","farm":1,"title":"P1400012","ispublic":1,"isfriend":0,"isfamily":0}]
I use this code in the Spring controller to deserialize the JSON:
Collection<Photos> readValues = objectMapper.readValue(new URL(url), new TypeReference<Collection<Photos>>() { });
And returns the following error:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
How can I solve this problem? I didn't found solutions.
Photos.class:
public class Photos {
#JsonProperty("page")
private Integer page;
#JsonProperty("pages")
private Integer pages;
#JsonProperty("perpage")
private Integer perpage;
#JsonProperty("total")
private Integer total;
#JsonProperty("photo")
#JsonDeserialize(contentAs = Photo.class, as = ArrayList.class)
private List<Photo> photo;
public Photos() {}
public Photos(Integer page, Integer pages, Integer perpage, Integer total,
List<Photo> photo) {
super();
this.page = page;
this.pages = pages;
this.perpage = perpage;
this.total = total;
this.photo = photo;
}
public Photos(List<Photo> photo) {
super();
this.photo = photo;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getPages() {
return pages;
}
public void setPages(Integer pages) {
this.pages = pages;
}
public Integer getPerpage() {
return perpage;
}
public void setPerpage(Integer perpage) {
this.perpage = perpage;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public List<Photo> getPhoto() {
return photo;
}
public void setPhoto(List<Photo> photo) {
this.photo = photo;
}
}
Photo.class:
public class Photo {
#JsonProperty("id")
private Integer id;
#JsonProperty("owner")
private String owner;
#JsonProperty("secret")
private String secret;
#JsonProperty("server")
private Integer server;
#JsonProperty("farm")
private Integer farm;
#JsonProperty("title")
private String title;
#JsonProperty("ispublic")
private Boolean isPublic;
#JsonProperty("isfriend")
private Boolean isFriend;
#JsonProperty("isfamily")
private Boolean isFamily;
public Photo() { }
public Photo(Integer id, String owner, String secret, Integer server,
Integer farm, String title, Boolean isPublic, Boolean isFriend,
Boolean isFamily) {
super();
this.id = id;
this.owner = owner;
this.secret = secret;
this.server = server;
this.farm = farm;
this.title = title;
this.isPublic = isPublic;
this.isFriend = isFriend;
this.isFamily = isFamily;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public Integer getServer() {
return server;
}
public void setServer(Integer server) {
this.server = server;
}
public Integer getFarm() {
return farm;
}
public void setFarm(Integer farm) {
this.farm = farm;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Boolean getIsPublic() {
return isPublic;
}
public void setIsPublic(Boolean isPublic) {
this.isPublic = isPublic;
}
public Boolean getIsFriend() {
return isFriend;
}
public void setIsFriend(Boolean isFriend) {
this.isFriend = isFriend;
}
public Boolean getIsFamily() {
return isFamily;
}
public void setIsFamily(Boolean isFamily) {
this.isFamily = isFamily;
}
}
The basic problem is that your json is not a Collection<Photos>, but a Map<String, Photos>, which has a single entry "photos" -> Photos instance.
I got your json to successfully deserialize by making the following changes...
A) Change the type being read:
Map<String, Photos> readValues = objectMapper.readValue(json, new TypeReference<Map<String, Photos>>() { });
Note that I read straight from a String (not a URL).
B) Change the type of Photo.id from Integer to Long, because your json has id values well exceeding max int size.
C) I added the missing two closing braces from your sample json to make it valid.
FYI, deserialization works with or without the #JsonDeserialize annotation on the List<Photo> photo field of Photos.
Here's some runnable code that works:
String json = "{\"photos\":{\"page\":1,\"pages\":60,\"perpage\":100,\"total\":\"5964\",\"photo\":[{\"id\":\"21577339501\",\"owner\":\"85277110#N02\",\"secret\":\"31e850dfeb\",\"server\":\"5785\",\"farm\":6,\"title\":\"P1390956\",\"ispublic\":1,\"isfriend\":0,\"isfamily\":0}, {\"id\":\"21577287101\",\"owner\":\"85277110#N02\",\"secret\":\"412990658f\",\"server\":\"611\",\"farm\":1,\"title\":\"P1400012\",\"ispublic\":1,\"isfriend\":0,\"isfamily\":0}]}}";
Map<String, Photos> readValues = new ObjectMapper().readValue(json, new TypeReference<Map<String, Photos>>() { });

Categories