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
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;
}
}
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
}
}
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
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;
}
}
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>>() { });