JSON Parsing Error no value for variable - java

I am doing a mobile app which retrieves information from my own API. I am trying to get a restaurant details in JSON and parsing them to be displayed. here is the error I am getting:
D/ViewRootImpl: MSG_RESIZED_REPORT: ci=Rect(0, 0 - 0, 0) vi=Rect(0, 0 - 0, 0) or=1
I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy#cf94aa3 time:148477558
E/MainActivity: Response from url: {
"address1": "Market Square, Smithfield, Dublin Dublin 7",
"address2": "Dublin 7",
"cost": 35,
"lat": 53.3489980000,
"lng": -6.2788120000,
"menu_type": "BBQ",
"name": "My Meat Wagon",
"offer": "Meal for 10\u20ac",
"phone": 53463267,
"rate": 4.1
}
E/MainActivity: Json parsing error: No value for restaurants
D/ViewRootImpl: #3 mView = null
and here is the code I am using:
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray restaurants = jsonObj.getJSONArray("restaurants");
// looping through the JSON object
JSONObject c = restaurants.getJSONObject(0);
String name = c.getString("name");
String address1 = c.getString("address1");
String address2 = c.getString("address2");
String lat = c.getString("lat");
String lng = c.getString("lng");
String cost = c.getString("cost");
String menu_type = c.getString("menu_type");
String rate = c.getString("rate");
String offer = c.getString("offer");
// Phone node is JSON Object
String mobile = c.getString("mobile");
// tmp hash map for single restaurant
HashMap<String, String> restaurant = new HashMap<>();
// adding each child node to HashMap key => value
restaurant.put("name", name);
restaurant.put("address1", address1);
restaurant.put("address2", address2);
restaurant.put("lat", lat);
restaurant.put("lng", lng);
restaurant.put("cost", cost);
restaurant.put("menu_type", menu_type);
restaurant.put("rate", rate);
restaurant.put("offer", offer);
restaurant.put("mobile", mobile);
contactList.add(restaurant);
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Json parsing error: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Couldn't get json from server. Check LogCat for possible errors!",
Toast.LENGTH_LONG)
.show();
}
});
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (pDialog.isShowing())
pDialog.dismiss();
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(
MainActivity.this, contactList,
R.layout.list_item, new String[]{"name", "address1",
"address2","lat","lng","menu_type","Phone","rate","offer","cost"}, new int[]{R.id.name,
R.id.address1, R.id.address2,R.id.lat,R.id.lng,R.id.menu,R.id.mobile,R.id.rate,R.id.offer,R.id.cost});
lv.setAdapter(adapter);
}
}
}

I would suggest to use Google Gson library for parsing json strings.
Basically you need to import the library, create corresponding POJO and call for gson.fromJson(jsonStringToParseFrom ,YourPOJOClassName.class). So your doInBackground will look like:
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Gson gson = new Gson();
YourPOJOClass parsedResponse = gson.fromJson(jsonStr, YourPOJOClass.class);
If there will be some parsing issues at gson you will get well informed exception of what went wrong and you will get rid off all the boilerplate parsing code.

Many APIs don't return an array when there is only a single result. You'll want to use optJSONArray and if it returns null, check if it's a single result (using another opt method), if it is, skip the array step.
https://docs.oracle.com/middleware/maf230/mobile/api-ref/oracle/adfmf/json/JSONObject.html#optJSONArray-java.lang.String-

Related

How to get the values from this json url?

I would like to access the data associated under the current dates of this json link. For instance, for the date : "2020-09-26",i would like to access the revenue associated under that date. I tried researching my question but i have not found anything helpful. Could someone assist me with this? So far, i already downloaded the json data and parsed it as well as extracted the revenue and date from the json file but i would like to get the revenue under each specified date.
https://financialmodelingprep.com/api/v3/income-statement/AAPL?limit=120&apikey=demo
private void downloadAnalystEstimateData(String api) {
// Initialize a new JsonArrayRequest instance
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(
Request.Method.GET,
api,
null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
// Do something with response
//mTextView.setText(response.toString());
//Log.i("jsonResponse", response.toString());
// Process the JSON
// Loop through the array elements
for (int i = 0; i < response.length(); i++) {
// Get current json object
try {
stockDetails = response.getJSONObject(i);
// Log.i("analyst estimate data..", stockDetails.toString());
dates = stockDetails.getString("date");
revenue = stockDetails.getString("revenue");
Log.i("revenue", revenue);
Log.i("dattes", dates);
// Log.i("estimatedRevenueLow", estimatedEbitdaLow);
//Log.i("revenueGrowth", estimatedRevenueLow);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Do something when error occurred
// Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT).show();
Log.i("error", error.toString());
// Toast.makeText(Analyze_Stocks_Activity.this, "An error occured....", Toast.LENGTH_SHORT).show();
}
}
);
// Add JsonArrayRequest to the RequestQueue
requestQueue.add(jsonArrayRequest);
}

TypeToken Object is not displayed correctly in the server

I'm new to TypeTokens and I'm having a problem. I have a shopping cart with products, and
those products I save to Shared Preferences using Typetoken. Because I need to delete and
remove products from recyclerview. Here what I have for adding products:
Gson gson = new Gson();
String json = preferences.getString("artikujtShporta", "");
ArrayList<Artikujt> artikullObject = gson
.fromJson(json, new TypeToken<ArrayList<Artikujt>>(){}.getType());
if (artikullObject != null) {
artikullObject.add(mArtikull);
String jsonString = gson.toJson(artikullObject);
mEditor.putString("artikujtShporta", jsonString);
mEditor.apply();
} else {
ArrayList<Artikujt> arrayArtikuj = new ArrayList<>();
arrayArtikuj.add(mArtikull);
Type listOfTestObject = new TypeToken<ArrayList<Artikujt>>() {}.getType();
String s = gson.toJson(arrayArtikuj, listOfTestObject);
mEditor.putString("artikujtShporta", s);
mEditor.apply();
}
Now I need to send this object to server with some additional information, as below:
private void sendBasketItemsToServer() {
//service where retrofit instance is defined for current route
ProductsService prodService = new ProductsService();
// Retrieve the product of the shopping cart which are saved in shred preferences
SharedPreferences preferences = getSharedPreferences(ITEMS_PREF, Context.MODE_PRIVATE);
SharedPreferences.Editor my_editor = preferences.edit();
String json = preferences.getString("artikujtShporta", "");
Gson gson = new Gson();
ArrayList<Artikujt> artikujt = gson
.fromJson(json, new TypeToken<ArrayList<Artikujt>>(){}.getType());
final int order_number = new Random().nextInt(26) + 75;
String date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
// initialize requestBody
RequestBody requestBody = null;
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("klienti", full_name);
jsonObject.put("adresa", fullAddress);
jsonObject.put("produktet", artikujt);
jsonObject.put("date", date);
jsonObject.put("order_number", String.valueOf(order_number));
requestBody = RequestBody.create(String.valueOf(jsonObject),
MediaType.parse("application/json; charset=utf-8"));
System.out.println(jsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
// Get token, stored in shared preferences
SharedPreferences editor = Objects.requireNonNull(getApplicationContext())
.getSharedPreferences(TOKEN_PREF, MODE_PRIVATE);
String token = editor.getString("token", "");
Callback<BasketResponse> callback = new Callback<BasketResponse>() {
#Override
public void onResponse(#NotNull Call<BasketResponse> call, Response<BasketResponse> response) {
if (response.isSuccessful()) {
// clear products added to cart
my_editor.clear();
my_editor.apply();
System.out.println(response.body());
Intent intent = new Intent(CheckoutActivity.this, SuccessOrderActivity.class);
startActivity(intent);
}
}
#Override
public void onFailure(#NotNull Call<BasketResponse> call, Throwable t) {
Toast.makeText(CheckoutActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
};
prodService.sendBasketItemsToServer(callback, token, requestBody);
}
All of the items are sent to server and I'm receiving a code 200 as response, but I have a
problem with products, with this line:
jsonObject.put("produktet", artikujt);
is displayed like this:
Is sending the name of the class, not products. When I debug in Android Studio, everything
seems okay
I have two days figuring out how to solve this, but I don't know how. Can someone have any
suggestion what I'm missing here or what I'm doing wrong. Thanks in advance.
Edit: I want to send to server a json like below:
{
"klienti": "my name",
"address": "my address",
"products": [
{
"id": 1,
"price": 2234,
"category": 3,
"created_at": 23-03-2020
},
{
"id": 2,
"price": 2534,
"category": 3,
"created_at": 23-03-2020
}
],
"date": 03-09-2020,
"order_number": 93
}
jsonObject.put("produktet", artikujt);
This line is simply adding the java object to jsonObject.
You can instead do
jsonObject.put("produktet", new Gson().toJson(artikujt));
Edit:
If you are using org.json.JSONObject, try
JSONArray jsonArray = new JSONArray();
artikujt.forEach(item -> {
jsonArray.put(new JSONObject(item));
});
jsonObject.put("produktet", jsonArray);
Though better solution would be to create a java class denoting your target json.
class ArtikujtData {
private String klienti;
private String address;
private List<Artikujt> products;
private String date;
#SerializedName(value = "order_number")
private String orderNumber;
// setters and getters
}
Create object of ArtikujtData and set values to it and use it as
requestBody = RequestBody.create(new Gson().toJson(artikujtData),MediaType.parse("application/json; charset=utf-8"));

ArrayList, print only the value

I have a contactList = new ArrayList<>(); where I store information in this format: "name", value_for_name.
I populate my contactList inside this function:
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray contacts = jsonObj.getJSONArray("results");
// looping through All Results
for (int i = 0; i < contacts.length(); i++) {
JSONObject c = contacts.getJSONObject(i);
String icon = c.getString("icon");
String id = c.getString("id");
String name = c.getString("name");
// tmp hash map for single contact
HashMap<String, String> contact = new HashMap<>();
// adding each child node to HashMap key => value
// contact.put("id", id);
contact.put("name", name);
// contact.put("email", icon);
// adding contact to contact list
contactList.add(contact);
}
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Json parsing error: " + e.getMessage(),
Toast.LENGTH_LONG)
.show();
}
});
}
} else {
Log.e(TAG, "Couldn't get json from server.");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"Couldn't get json from server. Check LogCat for possible errors!",
Toast.LENGTH_LONG)
.show();
}
});
}
return null;
}
The problem is that when I try to print a value:
System.out.println(contactList.get(position));
The output is in this format:
{name="Foo"}
I only want to print Foo
I tried also with: System.out.println(String.valueOf(contactList.get(position)));
but I always get the whole string: {name="Foo"}
Can you help me, please?
Do I really need to parse the string?
Try:
System.out.println(contactList.get(position).get("name"));
I see you have a hashmap into an array list so you want to get the object from "X" position from array and after that get the value from the hashmap by property name.

Android Login screen from Json

I´m newbie on Android and need help.
I have a JSON that looks like this:
{
"Id": 1,
"Name": "user",
"userId": 4,
"active": true,
"ProfileId": 1,
"Tema": "green",
"Language": "english",
"success": true,
"error": false
}
Json 2:
{"message":"no user or password","success":false,"erroAplicacao":false}
This is my code:
public class MainActivity extends AppCompatActivity {
EditText usernameWidget;
EditText passwordWidget;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
usernameWidget = (EditText) findViewById(R.id.tv_username);
passwordWidget = (EditText) findViewById(R.id.tv_password);
}// END ON CREATE
public class DownloadTask extends AsyncTask<String, Void, String> {
String message = "message";
String loginSuccess;
String Id = "Id";
#Override
protected String doInBackground(String... urls) {
String result = "";
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(urls[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
int data = reader.read();
while (data != -1){
char current = (char) data; // each time creates a char current
result += current;
data = reader.read();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
} // END doInBackground
//Method called when the doInBack is complete
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
JSONObject jsonObject = new JSONObject(result);
Log.i("***JSON ITSELF***", result);
loginSuccess = jsonObject.getString("success");
Log.i("*****LOGIN SUCCESS*****", loginSuccess);
message = jsonObject.getString("message");
Log.i("*****MESSAGE*****", message);
Id = jsonObject.getString("Id");
Log.i("*****ID*****", pessoaFisicaId);
}catch(JSONException e) {
e.printStackTrace();
}// END CATCH
if (loginSuccess.contains("true")){
Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
startActivity(intent);
}else if (loginSuccess.contains("false")){
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
}
}// END POST EXECUTE
}// END Download Task
public void login(View view) {
String user = usernameWidget.getText().toString();
String pass = passwordWidget.getText().toString();
String stringJSON = "*URL*login=" + user + "&senha=" + pass;
DownloadTask task = new DownloadTask();
task.execute(stringJSON);
Log.i("*****JSON URL*****", stringJSON);
}// END LOGIN
}// END MAIN
In this order:
loginSuccess = jsonObject.getString("success");
message = jsonObject.getString("message");
Id = jsonObject.getString("Id");
I get the message ("no user or password") from json2 (different url) as a Toast.
If I change the order, lets say, to:
loginSuccess = jsonObject.getString("success");
Id = jsonObject.getString("Id");
message = jsonObject.getString("message");
I don´t get a message. In fact I get the value "message" from the String message at the start of the DownloadTask class.
It seems that the json is only getting two values, the first ones I ask for.
One thing though is that only when the user or password is wrong is that the json has a message (json2):
{"message":"no user or password","success":false,"erroAplicacao":false}
Since my json cant be transformed into an array json (I tried and got error saying this), what should I do?
When you call jsonObject.getString("your_string"), this will throw a JSONException if your string cannot be found. Therefore, the remaining lines in of code in the method will not be executed. Change your LogCat settings to verbose and you should be able to see what's going on.
More info on the getString() method here:
https://developer.android.com/reference/org/json/JSONObject.html#getString(java.lang.String)
Use GSON
public class User{
private int Id;
private String Name;
}
Parse
User user = GSON.fromJSON(jsonString, User.class);

Volley String cannot be converted to JSONObject

I'm always getting the following error as long as i put a array into Params. Even after converting to String it still gives that error. The code works fine without the contactlist array inside it. Any idea?
Error
com.android.volley.ParseError: org.json.JSONException: Value Created
of type java.lang.String cannot be converted to JSONObject
Sample response:
{
"username": "test2",
"lists": [
"contact_0",
"contact_1",
"contact_2",
"contact_3",
"contact_4",
"contact_5",
"contact_6",
"contact_7",
"contact_8",
"contact_9"
]
}
ArrayList<String> contactList = new ArrayList<String>();
public String joinInfo;
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, null);
while (phones.moveToNext())
{
String name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
System.out.println("name : " + name + ", ID : " + phoneNumber);
joinInfo = name;
contactList.add(joinInfo);
}
phones.close();
RequestQueue rq = Volley.newRequestQueue(this);
JSONObject params = new JSONObject();
try {
params.put("username", "test2");
params.put("lists", contactList.toString()); // When i change this to simply "test" a string, it works fine.
Log.d("PANDA", contactList.toString());
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
"http://postcatcher.in/catchers/55521f03f708be0300001d28", params, //Not null.
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("PANDA", response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("PANDA", "Error: " + error.getMessage());
Log.d("PANDA", error.toString());
}
});
// Adding request to request queue
rq.add(jsonObjReq);
PostCatcher although allowing us to post requests, its response is basically a plain string "Created" and not in Json format. As such our client code is not able to ascertain it and throws error. One thing is even without ArrayList object that is with plain (String, String) K,V pair also it would fail.
You can verify it if you try sending request through Advanced Rest Client (see attached)

Categories

Resources