Dynamic json parsing using GSON -Android - android

I have two jsons
{
success: 1,
camera: [
{
productid: 18486,
productkey: 509,
categoryid: 85,
categorykey: 2,
productname: "Samsung",
productimage: "samsung.jpg",
price: "10900"
},
{
productid: 18458,
productkey: 508,
categoryid: 85,
categorykey: 2,
productname: "Nikon Coolpix L29",
productimage: "nikoncoolpix.jpg",
price: "4446"
}]
}
Second Json
{
success: 1,
mobile: [
{
productid: 9999,
productkey: 519,
categoryid: 852,
categorykey: 21,
productname: "Samsung grand",
productimage: "samsung.jpg",
price: "10900"
},
{
productid: 1858,
productkey: 58,
categoryid: 5,
categorykey: 12,
productname: "nokia",
productimage: "nokia.jpg",
price: "44462"
}]
}
I need to parse the json using GSON,I tried these code
Gson mJson = new Gson();
PDProduct mObj = (PDProduct) mJson.fromJson(jsonStr,PDProduct.class);
List<ProductObj> mobiles = null;
mobiles = mObj.mobiles;
for (int i = 0; i < mobiles.size(); i++) {
HashMap<String, String> ProductDetails = new HashMap<String,
String>();
ProductDetails.put(Tags.PRODUCTTAG_CATGORY_ID,
mobiles.get(i).categoryid);
ProductDetails.put(Tags.PRODUCTTAG_CATGORY_KEY,
mobiles.get(i).categorykey);
ProductDetails.put(Tags.PRODUCTTAG_PRODUCT_ID,
mobiles.get(i).productid);
ProductDetails.put(Tags.PRODUCTTAG_PRODUCT_KEY,
mobiles.get(i).productkey);
ProductDetails.put(Tags.PRODUCTTAG_PRODUCT_NAME,
mobiles.get(i).productname);
ProductDetails.put(Tags.PRODUCTTAG_PRODUCT_PIC,
mobiles.get(i).productimage);
ProductDetails.put(Tags.PRODUCTTAG_PRODUCT_PRICE,
mobiles.get(i).price);
ProductDetail.add(ProductDetails);
}
public class PDProduct {
public String success = null;
public List<PDProductObj> mobiles = null;
}
For this I'm getting only mobile data,How could dynamically create key?
Is there any other method to parse this data?

Your two JSON objects are two different objects; one has a field camera, one has a field mobile.
If you're the one producing that JSON the easiest answer is: fix the JSON. Use one field name and include something in the objects to denote a category (or whatever that is).
If you can't fix the JSON, you can write a custom deserializer that deals with it by renaming the field:
class MyDeserializer implements JsonDeserializer<PDProduct> {
#Override
public PDProduct deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException
{
JsonObject jo = je.getAsJsonObject();
if (jo.has("camera"))
{
JsonElement e = jo.remove("camera");
jo.add("mobile", e);
}
return new Gson().fromJson(jo, type);
}
}
Then use it with Gson:
Gson gson =
new GsonBuilder()
.registerTypeAdapter(PDProduct.class, new MyDeserializer())
.create();

The simplest solution is to change the json.
Add a new level "product" to the json and let it have name and data.
For example:
{
success: 1,
product:
{
name:camera,
data: [
{
productid: 18486,
productkey: 509,
categoryid: 85,
categorykey: 2,
...
Change PDIProduct class to reflect this change.
If you can't change the json (because you are getting it from an external source), change the JSON object to this structure before using GSON.

Related

How parse array of arrays JSON with Retrofit?

When I use retrofit, I get JsonSyntaxException : Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 3 path $[0] How can I parse it?
[
[
{
"resturan_name": "هتل شاه عباس",
"menu_name": "کباب سلطانی",
"food_name": "پیش غذا"
},
{
"resturan_name": "هتل شاه عباس",
"menu_name": "کباب سلطانی",
"food_name": "پیش غذا"
}
],
[
{
"resturan_name": "هتل شاه عباس",
"menu_name": "کباب سلطانی",
"food_name": "عصرانه"
},
{
"resturan_name": "هتل شاه عباس",
"menu_name": "کباب سلطانی",
"food_name": "عصرانه"
}
]
]
You have an array of array of objects. So, when you're parsing your JSON, you have to use JSONArray:
val jsonArray = JSONArray(your_json)
The json received has a list but you maybe use json object pars in rerofit
see this link for resolve
Parse JSON array response using Retrofit & Gson
Change
Call<...> getListOf....(...);
To
Call<List<...>> getListOf....(...);
Using Response Model
Make your Response Model Class like this Using Gson,
class ResponseModel : ArrayList<ResponseModel.ResponseModelSubList>(){
class ResponseModelSubList : ArrayList<ResponseModelSubList.ResponseModelSubListItem>(){
#Parcelize
data class ResponseModelSubListItem(
#SerializedName("food_name")
val foodName: String? = "",
#SerializedName("menu_name")
val menuName: String? = "",
#SerializedName("resturan_name")
val resturanName: String? = ""
) : Parcelable
}
}
Parse JSON like this,
val response = ResponseModel() // Here response is getting from retofit or other networking lib. you use.
for (i in 0 until response.size) {
val responseList = response[i]
for (j in 0 until responseList.size) {
var foodName = responseList[j].foodName
var menuName = responseList[j].menuName
var restaurantName = responseList[j].resturanName
}
}
Using Manually Parsing
val jsonArray = JSONArray(response)
for (i in 0 until jsonArray.length()){
val jsonArray1 = jsonArray.get(i) as JSONArray
for (j in 0 until jsonArray1.length()){
var jsonObj = jsonArray1.get(j) as JSONObject
var foodName = jsonObj.getString("food_name")
var menuName = jsonObj.getString("menu_name")
var restaurantName = jsonObj.getString("resturan_name")
}
}

fetching value of specific key from json response

how can I store a specific value of a key from json response into a variable
{
"results": [
{
"name": ryan,
"roll_id": 64,
"class_id": 310,
"net_id": 95,
},
],
};
above is the json response :-
val gson = GsonBuilder().create()
val ListV = gson.fromJson(body, HomeClass::class.java)
after these 2 lines I'm totally clueless how to do it I've gone through Internet but It was hard for me to understand how to proceed further.
Your Json Structure will be
{
"results": [
{
"name": "Amiyo",
"roll_id": 1,
"class_id": 10,
"net_id": 91
},
{
....
}
]
}
Data class should be
data class HomeClass (
#SerializedName("results") val results : List<Results>
)
data class Results (
#SerializedName("name") val name : String,
#SerializedName("roll_id") val roll_id : Int,
#SerializedName("class_id") val class_id : Int,
#SerializedName("net_id") val net_id : Int
)
fromJson
val listData = gson.fromJson(jsonData, HomeClass::class.java)
Then
val totalSize = 0 until listData!!.size
if(totalSize.size>0)
{
for (i in totalSize)
{
//Your Code i==Position
}
}

Gson deserialize list from JSON object

I make calls to an api that returns the following structure:
{
page: 1,
results: [
{
poster_path: "/6FxOPJ9Ysilpq0IgkrMJ7PubFhq.jpg",
adult: false,
overview: "Tarzan, having acclimated to life in London, is called back to his former home in the jungle to investigate the activities at a mining encampment.",
release_date: "2016-06-29",
genre_ids: [
28,
12
],
id: 258489,
original_title: "The Legend of Tarzan",
original_language: "en",
title: "The Legend of Tarzan",
backdrop_path: "/75GFqrnHMKqkcNZ2wWefWXfqtMV.jpg",
popularity: 27.931248,
vote_count: 655,
video: false,
vote_average: 4.6
},
... MORE MOVIES ...
}
The part that I am interested in is JUST the array of movie objects.
My movie class has the following method:
public static TypeAdapter<Movie> typeAdapter(Gson gson) {
return new AutoValue_Movie.GsonTypeAdapter(gson);
}
And this is how I build the Gson object that I pass to my retrofit instance:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new AutoValueGsonTypeAdapterFactory())
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.create();
I use the following method in my DataManager to make the api call:
public Observable<Movie> syncMovies(int page) {
return mMovieService.getPlayingMovies(page)
.concatMap(new Func1<List<Movie>, Observable<Movie>>() {
#Override
public Observable<Movie> call(List<Movie> movies) {
return mDatabaseHelper.setMovies(movies);
}
});
}
Get playing movies returns an Observable< List< Movie > >. The problem is that I get an error message saying: Expected BEGIN_ARRAY but was BEGIN_OBJECT.
I think that the problem is that my JSON is really an object. How can I just extract the array and parse it into a List< Movie >?
Sorry for the ignorance but I am completely new to Gson.

How to parse JsonObject to List<MyClass> using gson

I need a list of objects and I'm having problems to get it. I'm pretty new using this so someone who can help me?
I'm using volley to get a jsonObject and then I need convert it(I saw the best wa to do this is with gson). Below you can see how looks an example of my json.
{
network: {
company: "JCDecaux",
href: "/v2/networks/dublinbikes",
id: "dublinbikes",
location: {
city: "Dublin",
country: "IE",
latitude: 53.3498053,
longitude: -6.2603097
},
name: "dublinbikes",
stations: [
{
empty_slots: 37,
extra: {
address: "Fitzwilliam Square East",
bonus: false,
connected: "1",
last_update: "1434047944",
open: true,
slots: 40,
ticket: true,
uid: 89
},
free_bikes: 3,
id: "153ff4dfb7bd8912ef91c10849129c2e",
latitude: 53.335211,
longitude: -6.2509,
name: "Fitzwilliam Square East",
timestamp: "2015-06-11T18:41:31.11Z"
},
{
empty_slots: 0,
extra: {
address: "Portobello Harbour",
bonus: false,
connected: "1",
last_update: "1434047764",
open: true,
slots: 30,
ticket: false,
uid: 34
},
free_bikes: 30,
id: "3c0cfd547a142bb651280991a412bcbe",
latitude: 53.330362,
longitude: -6.265163,
name: "Portobello Harbour",
timestamp: "2015-06-11T18:41:31.15Z"
},
... ect
Station class
public class Station {
public Station(){}
public String StationName;
public String Distance;
public String Slots;
public String Bikes;
public String LastUpdate;
//Getters and Setters ...
}
Below you can see what I have done so far..
//stations
JSONObject jsonNetwork = new JSONObject(response.getString("network"));
Type listType = new TypeToken<ArrayList<Station>>() {
}.getType();
List<Station> yourClassList = new Gson().fromJson(jsonNetwork, listType);
But I don't know how to parse all this and avoid the data I dont need and also the function Gson().fromJson needs and JsonArray and what I have is a JsonObject
Thanks for your time!
If all that you are looking for are the stations then I think you should do the following:
//stations
JSONObject jsonNetwork = new JSONObject(response.getString("network"));
JSONArray stationsArray = jsonNetwork.getJSONArray("stations");
Now, you should pass this stationsArray variable to the fromJson method. Also, the variable names of your Station class should be equal to the key names that you want to extract from your json. There is a good example in the following link:
http://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/
Use below code
Gson gson = new Gson();
YourClass obj = gson.fromJson(jsonObject.toString(), YourClass.class);

How to parse this JSON response with GSON after a Retrofit GET request?

I'm trying to parse a JSON response using GSON after a Retrofit GET request. I don't need all the keys and values so I only #Expose the ones that I need and instructed the parser to do so. The request fires OK and the response come clean, but looking into logcat I found this error which evidently points me that POJO model is bad formatted or implemented:
04-09 12:16:01.679 5604-5604/? V/Retrofit error﹕ retrofit.converter.ConversionException: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
This is the JSON response (which returns ok after GET request):
{
objects: [
{
rating: 0.97,
name: "High Line",
ranking: 0,
url: "http://www.thehighline.org",
price: null,
phone: "2125006035",
last_sync: 1428328869,
photos: [
"https://irs3.4sqi.net/img/general/original/11402168_2zKtnTfWXPJJJAaX7N6g1EMPTR7ahNqSAOsMotN-jNU.jpg"
],
local_id: 13778,
likes: 0,
city_id: 2621,
address: "btwn Gansevoort & W 34th St",
resource_uri: "/api/v1/venues/40f1d480f964a5206a0a1fe3/",
id: "40f1d480f964a5206a0a1fe3",
categories: [
{
name: "Park",
parent: {
local_id: 7,
name_id: "sights",
name: "Landmarks",
id: "4d4b7105d754a06377d81259"
},
local_id: 494,
name_id: "park",
category_id: 7,
id: "4bf58dd8d48988d163941735"
}
],
location: {
lat: 40.7470618874989,
lng: -74.0051937103271
}
},
{
rating: 0.97,
name: "Central Park",
ranking: 0,
url: "http://www.centralparknyc.org",
price: null,
phone: "2123106600",
last_sync: 1428521923,
photos: [
"https://irs2.4sqi.net/img/general/original/655018_Zp3vA90Sy4IIDApvfAo5KnDItoV0uEDZeST7bWT-qzk.jpg"
],
local_id: 13826,
likes: 0,
city_id: 2621,
address: "59th St to 110th St",
resource_uri: "/api/v1/venues/412d2800f964a520df0c1fe3/",
id: "412d2800f964a520df0c1fe3",
categories: [
{
name: "Park",
parent: {
local_id: 7,
name_id: "sights",
name: "Landmarks",
id: "4d4b7105d754a06377d81259"
},
local_id: 494,
name_id: "park",
category_id: 7,
id: "4bf58dd8d48988d163941735"
}
],
location: {
lat: 40.7888599444948,
lng: -73.9611625671387
}
}
],
meta: {
total_count: 1344,
next: "/api/v1/venues/?city_id=2621&category=topPicks&offset=2&limit=2&format=json",
limit: 2,
offset: 0
}
}
This is the main activity call to the Retrofit service:
Map<String, String> params = new HashMap<String, String>();
params.put("city_id", "2621");
params.put("offset", "0");
params.put("limit", "2");
params.put("category", "topPicks");
params.put("format", "json");
ApiClient.getApiClient().listVenues(params, new Callback<List<ApiResponse>>() {
#Override
public void success(List<ApiResponse> venues, Response response) {
//consumir venues
Log.v("RETROFIT SUCCESS", response.getBody().toString());
mAdapter = new MainCustomAdapter(venues);
mRecyclerView.setAdapter(mAdapter);
}
#Override
public void failure(RetrofitError retrofitError) {
if (retrofitError.getResponse() != null) {
Log.v("Retrofit error", retrofitError.getCause().toString());
}
//manejar el fallo
}
});
This is the Api client:
public class ApiClient {
private static ApiVenuesInterface apiVenues;
public static ApiVenuesInterface getApiClient() {
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
if (apiVenues == null) {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("http://endpoint.com")
.setConverter(new GsonConverter(gson))
.setLogLevel(RestAdapter.LogLevel.FULL).setLog(new AndroidLog("RETROFIT"))
.build();
apiVenues = restAdapter.create(ApiVenuesInterface.class);
}
return apiVenues;
}
public interface ApiVenuesInterface {
//llamada asíncrona al querystring de venues
#GET("/api/v1/venues")
void listVenues(#QueryMap Map<String, String> params, Callback<List<ApiResponse>> callback);
}}
And finally this my POJO model (which I believe is the place where the main problem is):
public class ApiResponse {
private List<Object> objects = new ArrayList<Object>();
}
class Object {
#Expose
private String name;
#Expose
private List<String> photos = new ArrayList<String>();
#Expose
private String address;
#Expose
private List<Category> categories = new ArrayList<Category>();
/**
*
* #return
* The name
*/
public String getName() {
return name;
}
/**
*
* #return
* The photos
*/
public List<String> getPhotos() {
return photos;
}
/**
*
* #return
* The address
*/
public String getAddress() {
return address;
}
/**
*
* #return
* The categories
*/
public List<Category> getCategories() {
return categories;
}
class Category {
#Expose
private String name;
/**
*
* #return
* The name
*/
public String getName() {
return name;
}
}}
So, how did I must to model my POJO to parse the data I need? Thanks in advance.
IMPORTANT EDIT: This question is valid for Retrofit 1.x. Be aware that Retrofit 2.x is a little bit different than this because it uses annotations and Call methods.
As per earlier comment:
Based on a quick look, your Callback return type isn't of type List<ApiResponse>, but rather just ApiResponse. If you change the following, things should start working:
public interface ApiVenuesInterface {
//llamada asíncrona al querystring de venues
#GET("/api/v1/venues")
void listVenues(#QueryMap Map<String, String> params, Callback<ApiResponse> callback);
}
At the moment, you're telling Gson to convert the response into a list of ApiResponse objects, but in reality it's just a single ApiResponse wrapping a list/array of items. You modelled the POJOs correctly, but not so much the retrofit callback.
[edit] answering your follow up question: you can access the wrapped objects by simply adding a getter to your ApiResponse class:
public List<Object> getObjects() {
return objects;
}
A small tip: it would be good to come up with a different name for your Object class, since its name is identical to the 'mother' of all objects in Java: java.lang.Object. This is bound to lead to confusion and very prone to importing/referencing errors. Try to come up with something a little more descriptive, for example Venue (as it appears that's what you're dealing with, although I may be mistaken).
[edit2] Gson produces an ApiResponse object, which wraps around a List<Object>. Iterating over that list can be done like any other Java iteration; i.e. using the enhanced for-loop:
for (Object object : getObjects()) {
// get the name for this object
String name = object.getName();
// get the address for this object
String address = object.getAddress();
// get all the photo urls for this object
List<String> photos = object.getPhotos();
// etc...
}
The reason you're seeing i.e. myjavapackage.Object#3c4a86e1 is because Java doesn't know how to represent your objects as a string for printing. You can change this representation by overriding the following method in your Object class:
#Override public String toString() {
// return a string representation for this object; i.e. its name:
return name;
}
I'd still recommend to rename your Object class to something more sensible to avoid confusing it with the built-in java.lang.Object.
Try to remove this part from json string
{
objects:
and last curly bracket.

Categories

Resources