Android and Json parsing - java

im trying to have my app connect to a rest API and pull the data from it. Ive so far pulled the data . but i dont know how to parse it. i believe thats what you do next.
here a snippet of my code that conencts to my rest API and gets the data . the error i get is JSONArray cannot be converted to JSONObject
if (status == 200) {
InputStream is = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String responseString;
StringBuilder sb = new StringBuilder();
while ((responseString = reader.readLine()) != null) {
sb = sb.append(responseString);
}
String speciesListData = sb.toString();
species= SpeciesJson.fromJson(speciesListData);
Log.d(Constants.TAG, "speciesJSON: " + species);
return true;
}
this is were i tried to parse it , it was working fine up until here. hers is the line were i try to parse it
species= SpeciesJson.fromJson(speciesListData);
and this thats were it broke lol
public class SpeciesJson {
private String scientific_name, name,description;
public SpeciesJson (JSONObject species) throws JSONException {
this.scientific_name=species.optString("scientific_name");
this.name=species.optString("name");
this.description=species.optString("description");
}
public static ArrayList<SpeciesJson> fromJson(String photoData) throws JSONException {
ArrayList<SpeciesJson> speciesData = new ArrayList<>();
JSONObject data = new JSONObject(photoData);
JSONObject photos = data.optJSONObject("name");
JSONArray photoArray = photos.optJSONArray("name");
for (int i = 0; i < photoArray.length(); i++) {
JSONObject photo = (JSONObject) photoArray.get(i);
SpeciesJson currentPhoto = new SpeciesJson(photo);
speciesData.add(currentPhoto);
}
return speciesData;
}
so when i run it using the parsing method i made, it doesnt not work.
the sample of hte json data is below, im trying to show the scientific_name and name in a view
{
"id": 1,
"scientific_name": "Platanus racemosa",
"name": "California Sycamore",
"description": "typically in river areas, but planted all throughout L.A",
"type": 1
},
{
"id": 2,
"scientific_name": "Pyrus kawakamii",
"name": "Ornamental Pear",
"description": "native to Asia, commonly planted in L.A",
"type": 1
},
{
"id": 3,
"scientific_name": "Liquidambar styraciflua",
"name": "American Sweetgum",
"description": "native to SE U.S, planted all around L.A",
"type": 1
},
{
"id": 4,
"scientific_name": "Setophaga coronata",
"name": "Yellow-rumped Warbler",
"description": "native bird, spends the winter in L.A before migrating north during the summer to breed",
"type": 2
},
{
"id": 5,
"scientific_name": "Calypte anna",
"name": "Anna's Hummingbird",
"description": "native bird, does not migrate. Spends the year in L.A",
"type": 2
},
{
"id": 6,
"scientific_name": "Regulus calendula",
"name": "Ruby-crowned Kinglet",
"description": "native bird, spends the winter in L.A before migrating north during the summer to breed",
"type": 2
}
]

My Dear Friend Use googles GSON Library that's it.
And For Your Help I made this little bit easier.
Make This Class SpeciesJson.java
public class SpeciesJson {
private String scientific_name;
private String name;
private String description;
public SpeciesJson() {
}
public SpeciesJson(String scientific_name,String name,String description) {
this.scientific_name = scientific_name;
this.name = name;
this.description = description;
}
//And getter,setters
}
If SpeciesJson Is simple an object then use this
Gson gson = new Gson();
SpeciesJson species = gson.fromJson(responseString,SpeciesJson.class);
If SpeciesJson Is an ArrayList then use this (Its Looks Like Your Case So Check This As Your Json Response Consist Multiple SpeciesJson Objects)
Gson gson = new Gson();
ArrayList<SpeciesJson> species = new ArrayList<>();
SpeciesJson[] speciesarray = (SpeciesJson[]) gson.fromJson(responseString,SpeciesJson[].class);
Collections.addAll(species, speciesarray);
And If You wanna learn something more about Gson Library check this link
https://guides.codepath.com/android/Leveraging-the-Gson-Library

Well you can use GSON to parse the data and Volley to get the data.
//Create volley request
String url = String.format("SOME_URL", arrayOfObject);
RequestQueue queue = VolleyService.getInstance(this.getContext()).getRequestQueue();
StringRequest request = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// we got the response, now our job is to handle it
try {
ArrayList<SpeciesJson> speciesData = getDataFromJson(stream);
} catch (RemoteException | OperationApplicationException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//something happened, treat the error.
Log.e("Error", error.toString());
}
});
queue.add(request);
//If your JSON data is an Array
private static List<SpeciesJson> getDataFromJson(String json) {
Gson gson = new GsonBuilder().create();
List<SpeciesJson> result = new ArrayList<>();
try {
JSONObject posts=new JSONObject(json);
JSONArray dataArray=posts.getJSONArray("data");
for(int n = 0; n < dataArray.length(); n++)
{
JSONObject object = dataArray.getJSONObject(n);
result.add(gson.fromJson(object.toString(), SpeciesJson.class));
}
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
And volley Service
public class VolleyService {
private static VolleyService instance;
private RequestQueue requestQueue;
private ImageLoader imageLoader;
private VolleyService(Context context) {
requestQueue = Volley.newRequestQueue(context);
imageLoader = new ImageLoader(requestQueue, new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap> cache = new LruCache<String, Bitmap>(20);
#Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url,bitmap);
}
});
}
public static VolleyService getInstance(Context context) {
if (instance == null) {
instance = new VolleyService(context);
}
return instance;
}
public RequestQueue getRequestQueue() {
return requestQueue;
}
public ImageLoader getImageLoader() {
return imageLoader;
}
}
Or you can use Retrofit library to parse it for you:
http://www.vogella.com/tutorials/Retrofit/article.html
https://github.com/codepath/android_guides/wiki/Consuming-APIs-with-Retrofit

You should use retrofit library with GsonConverterFactory. The best solution to manage network response.

Related

How to use gson for getstring of json?

I am new to use gson.
I found a lots of tutorial there I can learn of gson but there are using recylerview and model file.
JsonObjectRequest request = new JsonObjectRequest(LoginUrl, new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d(TAG , String.valueOf(response));
try {
String statusObject = response.getString("status");
String msgObject = response.getString("msg");
if (statusObject.equals("200")) {
JSONArray jsonArray = response.getJSONArray("response");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject managerResponse= jsonArray.getJSONObject(i);
// userIdObject = managerResponse.getString("user_id");
// String nameObject = managerResponse.getString("name");
// String emailObject = managerResponse.getString("email");
// String mobileObject = managerResponse.getString("mobile");
// String postobject = managerResponse.getString("post");
// pojectObject = managerResponse.getString("project");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
}
Here I can get data from jsonrequest using volley but unable to do that same process using volley and gson. Is there any way to use gson?
Thank You.
Update
My JSON Response
{
"status": "200",
"msg": "Successfully",
"response": [
{
"user_id": "1",
"name": "HEMANT OJHA",
"email": "hemguna#gmail.com",
"mobile": "9584919991",
"address1": "C92, PALLAWI NAGAR BABADIYA KALAN",
"user": "admin",
"api_token": "admin"
}
]
}
Generating POJO class from JSON
// Considering your response consists of json objects & json array
// Create a POJO class for your response with the link above
{
"keyOne": 1,
"keyTwo": "Some Value",
"someArray": [{
"key": "Value"
},
{
"key": "Value"
}
]
}
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class ExampleClass {
#SerializedName("keyOne")
#Expose
private int keyOne;
#SerializedName("keyTwo")
#Expose
private String keyTwo;
#SerializedName("someArray")
#Expose
private List<SomeArray> someArray = null;
public int getKeyOne() {
return keyOne;
}
public void setKeyOne(int keyOne) {
this.keyOne = keyOne;
}
public String getKeyTwo() {
return keyTwo;
}
public void setKeyTwo(String keyTwo) {
this.keyTwo = keyTwo;
}
public List<SomeArray> getSomeArray() {
return someArray;
}
public void setSomeArray(List<SomeArray> someArray) {
this.someArray = someArray;
}
}
// Parsing JSON response with GSON
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
ExampleClass resultObj = gson.fromJson(jsonObject.toString(), ExampleClass.class);
int keyOneValue = resultObj.getKeyOne() // First JSON Object
// Getting String value
String keyTwoValue = resultObj.getKeyTwo() // Second JSON Object
List<SomeArray> yourJSONArray = resultObj.getSomeArray() // Getting JSON Array contents
// Depending on JSON response that you've updated in your question
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
ExampleClass resultObj = gson.fromJson(jsonObject.toString(),ExampleClass.class);
String status = resultObj.getStatus();
String msg = resultObj.getMsg();
List<Response> responseList = resultObj.getResponse();
The best way to use for entire app is create a Utils class and use it for conversion.
GsonUtils.java
// This Class is useful for mapping Json into Java Objects and vice versa.
public class GsonUtils {
private static final Gson gson = new Gson();
// This will Convert Java Objects into JSON String...
public static String toGson(Object object) {
return gson.toJson(object);
}
// Gives Java Objects from JSON
public static <T> T fromGson(String json, Class<T> type) {
return gson.fromJson(json, type);
}
public static JsonArray fromGson(String json) {
return new JsonParser().parse(json).getAsJsonArray();
}
}
Now convert any json to and from POJO via,
POJO pojoObj = GsonUtils.toGson(POJO.class);
Try this
JSON response
String str = new Gson().toJson(response)

How to modify Json structure in java (Android App)?

I'm developing an Android application that consumes data from a Json API. That Json API returns a array of objects like this:
[
{
"idProduct": 1,
"price": 25.9,
"tpPrice": v1
},
{
"idProduct": 1,
"price": 29.9,
"tpPrice": v2
},
{
"idProduct": 2,
"price": 19.9,
"tpPrice": v1
},
{...}
]
As you can see, the API returns two objects with the same ID, but with different prices.
I want to implement a solution that I can modify this json to something like this:
[
{
"idProduct": 1,
"prices": [
{
"price": "25.9,
"tpPrice": v1
},
{
"price": "29.9,
"tpPrice": v2
}
]
},
{
"idProduct": 2,
"prices" [
{
"price": "19.9,
"tpPrice": v1
}
]
},
{...}
]
Thats my WebServiceManager if its necessary, I'm using Gson.
public class WebServiceManager extends AsyncTask<String, String, List<Object>> {
private IWebServiceManager iWebServiceMngr;
private Context ctx;
private ProgressDialog progress;
private String messageError = null;
private String bean = null;
//private final String URL = "http://192.168.7.1:8080/WSPrePedidos/api/consulta/";
private final String URL_BASE = "/WSPrePedidos/api/consulta/";
private final String PATH = "br.com.example.model.";
#Override
protected void onPreExecute() {
super.onPreExecute();
progress = new ProgressDialog(ctx);
progress.setCancelable(false);
progress.setMessage(ctx.getString(R.string.progress_start));
progress.show();
}
/**
* 0 - Access
* 1 - Parameters
* 2 - Class
*
* #param params
* #return
*/
#Override
protected List<Object> doInBackground(String... params) {
bean = params[2].toString();
publishProgress(ctx.getString(R.string.progress_middle));
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
List<Object> lstObj = new ArrayList<>();
try {
URL url = new URL(params[0] + URL_BASE + params[1]);
Log.i("URL: ", url.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(50000);
urlConnection.setReadTimeout(50000);
urlConnection.connect();
int cdResposta = urlConnection.getResponseCode();
InputStream inputStream;
if (cdResposta < HttpURLConnection.HTTP_BAD_REQUEST) {
Log.i("InputStream Ok: ", "" + cdResposta);
inputStream = urlConnection.getInputStream();
} else {
Log.i("InputStream ferrado: ", "" + cdResposta);
inputStream = urlConnection.getErrorStream();
messageError = ctx.getString(R.string.message_fail_generic);
}
reader = new BufferedReader(new InputStreamReader(inputStream));
JsonElement je = new JsonParser().parse(reader);
Gson gson = new Gson();
if (!je.isJsonObject()) {
for (JsonElement element : je.getAsJsonArray()) {
lstObj.add(gson.fromJson(element.getAsJsonObject(), Class.forName(PATH + bean)));
}
} else if (je.isJsonObject()) {
messageError = null;
JsonObject jsonObject = je.getAsJsonObject();
if (jsonObject.get("error") == null) {
lstObj.add(gson.fromJson(je.getAsJsonObject(), Class.forName(PATH + bean)));
}
}
} catch (Exception e) {
e.printStackTrace();
messageError = ctx.getString(R.string.message_fail_connect_server);
} finally {
try {
if (urlConnection != null)
urlConnection.disconnect();
if (reader != null)
reader.close();
} catch (IOException e1) {
//e1.printStackTrace();
}
}
return lstObj;
}
#Override
protected void onProgressUpdate(String... params) {
progress.setMessage(params[0]);
}
#Override
protected void onPostExecute(List<Object> lstObj) {
super.onPostExecute(lstObj);
iWebServiceMngr.posExecuteAsyncTaskResult(lstObj, bean, messageError);
progress.dismiss();
}
public WebServiceManager(Context ctx, IWebServiceManager iWebServiceMngr) {
this.ctx = ctx;
this.iWebServiceMngr = iWebServiceMngr;
}
}
Sorry for my bad english.
I tried to be as specific as possible.
Create a "Product" Object that contains a map of prices. On your JSON response iterate through it and use the logic:
If a product doesn't exist, create the product and apply the price.
If it does exist and the price ID also does, overwrite the price.
If it does exist and the price ID doesn't exists, add the price to the map.

Parsing json which has an object in two formats

I have a json object as below.
{
"products": [
{
"details": {
"name": "xxx",
"price": "100rs"
},
"description": "Buy this product"
}, {
"details": [{
"name": "yyy",
"price": "200rs"
}],
"description": "another project"
}
]
}
Here the details are presented in 2 formats. How can I create a POJO (Plain Old Java Object) class of this to use for the Retrofit api?
I think that's bad api response and should be fixed from backend. But if you want to address the problem, you have to deserialize response to String using String converter. You can't do deserialize it to your Pojo using Gson converter.
StringConverter.java
public class StringConverter implements Converter {
#Override
public Object fromBody(TypedInput typedInput, Type type) throws ConversionException {
String text = null;
try {
text = fromStream(typedInput.in());
} catch (IOException ignored) { }
return text;
}
#Override
public TypedOutput toBody(Object o) {
return null;
}
public static String fromStream(InputStream in) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder out = new StringBuilder();
String newLine = System.getProperty("line.separator");
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
out.append(newLine);
}
return out.toString();
}
}
API Call implementation
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL)
.setConverter(new StringConverter())
.build();
YourAPI api = restAdapter.create(YourAPI.class);
api.yourService(parameter,new RestCallback<String>() {
#Override
public void success(String response, Response retrofitResponse) {
super.success(response, retrofitResponse);
//process your response here
//convert it from string to your POJO, JSON Object, or JSONArray manually
}
#Override
public void failure(RetrofitError error) {
super.failure(error);
}
});

JSON object not displaying values after fetching from database

I am fetching data from database in android and i can see data fetching from databse in JSON format using POSTMAN but when i am trying to display it in my android application, its not displaying any value.
Values from POSTMAN:
{
"result": [
{
"Date": "18-3-2016",
"Events": "Local Holiday"
},
{
"Date": "23-3-2016",
"Events": "Monthly Fees"
},
{
"Date": "15-4-2016",
"Events": "Monthly Fees"
},
{
"Date": "23-4-2016",
"Events": "Annual Day"
},
{
"Date": "30-4-2016",
"Events": "session end"
},
{
"Date": "9-4-2016",
"Events": "Parent Teacher Meeting"
}
]
}
I am following some tutorials and Code using:
private void getData() {
loading = ProgressDialog.show(this,"Please wait...","Fetching...",false,false);
String url = config_events.DATA_URL;
StringRequest stringRequest = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
loading.dismiss();
showJSON(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(events.this,error.getMessage().toString(),Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
private void showJSON(String response) {
String date = "";
String comment="";
//String vc = "";
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray result = jsonObject.getJSONArray(config_events.JSON_ARRAY);
JSONObject collegeData = result.getJSONObject(0);
date = collegeData.getString(config_events.KEY_NAME);
comment = collegeData.getString(config_events.KEY_ADDRESS);
//vc = collegeData.getString(config_events.KEY_VC);
} catch (JSONException e) {
e.printStackTrace();
}
textViewResult.setText("Date:"+date + "Comment:"+ comment);
Assuming that you have tried to debug it, this could be the problem of user-permissions in Android manifest. Make sure that you have following permissions in your manifest file.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
if you really getting the response through the API you might want to check the JSON parsing code this is something I wrote while assuming the response in the question
private void showJSON(String response){
try{
Log.d(TAG, "showJSON: \n"+response);// print here to check you are getting the right response
JSONObject response_JsonObject = new JSONObject(response);
JSONArray result_JsonArray = response_JsonObject.getJSONArray("result");
ArrayList<Event> events = new ArrayList<>();
for (int i = 0; i < result_JsonArray.length(); i++) {
Event single_Event = new Event();
single_Event.setDate(result_JsonArray.getJSONObject(i).getString("Date"));
single_Event.setEvent(result_JsonArray.getJSONObject(i).getString("Events"));
events.add(single_Event);
}
Log.d(TAG, "showJSON: Event list size: "+events.size()); // check number of elements
}catch (Exception e){
e.printStackTrace();
}
}
private class Event{
private String date;
private String event;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}
}

Recursive Method to create Json object

I like to know how I might do the following:
I want to create a json format of the following:
I want to be able to create a recursive function that takes an object holding a list of other objects of the same type and in a method to recursively create the format below.
{
"name": "lib",
"contains": [{
"name": "room",
"contains": [{
"name": "bookshelf",
"contains": [{
"name": "shelf",
"contains": []
}]
}]
}]
}
I have this as the following method:
private JSONObject json = new JSONObject();
public JSONObject setupLib(Contains contain) {
int count = contain.getContainerList().size();
for(int i = 0; i < count; i++){
try {
json.put("name", contain.getContainerList().get(i).getContainerName());
if(contain.getContainerList().size() != 0) {
Contains contains = (Contains) contain.getContainerList().get(i);
JSONArray array = new JSONArray();
json.put("contain",array.put(setupLib(contains)));}
}catch (JSONException e){
Log.i(Tag, e.getMessage());
}
}
return json;
}
I get a stackoverflow on the array/object
Two options
Do it yourself recursively
Use a library such as Gson to save you the development time and effort
Since this is a learning experience, I have shown both that return this JSON.
{
"name": "lib",
"contains": [{
"name": "room",
"contains": [{
"name": "bookshelf",
"contains": [{
"name": "shelf",
"contains": []
}]
}]
}]
}
public static void main(String[] args) {
Contains lib = new Contains("lib");
Contains room = new Contains("room");
Contains bookshelf = new Contains("bookshelf");
Contains shelf = new Contains("shelf");
bookshelf.add(shelf);
room.add(bookshelf);
lib.add(room);
// Option 1
System.out.println(setupLib(lib).toJSONString());
// Option 2
Gson gson = new Gson();
System.out.println(gson.toJson(lib));
}
private static JSONObject setupLib(Contains contain) {
if (contain == null) return null;
LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
JSONArray array = new JSONArray();
for (Contains c : contain.getContainerList()) {
JSONObject innerContain = setupLib(c);
if (innerContain != null) {
array.add(innerContain);
}
}
map.put("name", contain.getName());
map.put("contains", array);
return new JSONObject(map);
}
This is the model object, for reference
public class Contains {
#SerializedName("name")
#Expose
private String name;
#SerializedName("contains")
#Expose
private List<Contains> contains;
public Contains(String name) {
this.name = name;
contains = new ArrayList<Contains>();
}
public void setName(String name) {
this.name = name;
}
public void add(Contains c) {
this.contains.add(c);
}
public void setContainerList(List<Contains> contains) {
this.contains = contains;
}
public String getName() {
return name;
}
public List<Contains> getContainerList() {
return this.contains;
}
}
I think is far easier if you'd serialize both the JSONObject and Contains classes. This way you'll be able to use the Jackson library to create the JSON file for you.
You can find more information about the Jackson library on the following GitHub page: https://github.com/FasterXML/jackson.

Categories