I am trying to display data from a rest api containing a Json Array and a list of Json objects. I tried following a tutorial and was able to display the data on textview. What I actually want to do is gather the data in a Hashmap in terms of key and value pair and sort them accordingly.
public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
if(!response.isSuccessful()){
textView.setText("Code: " +response.code());
return;
}
int j=0;
List<Post> posts = response.body();
Map<Integer,String> data = new HashMap<Integer, String>();
// Iterating through post and saving data in content variable
for(Post post: posts)
{
String content ="";
//String name = post.getName();
if(!(post.getName()==(null)) && !(post.getName().equals("")))
{
data.put(post.getListid(),post.getName()); //For inserting data into hashmap
content += "ListID: " + post.getListid() + "" + "\n";
content += "Name: " + post.getName() + "" + "\n";
}
textView.append(content);
}
The current code saves the data in a content variable and displays it in the text view.
I am relatively new to using hashmap and retrofit for displaying data. I would really appreciate if someone could explain me where I am going wrong with my code. I tried printing out the data but was only able to print the last line and not the rest.
This is my Json file that I want to sort and display the data
[{"listId":2,"name":null},{"listId":2,"name":"Item 990"},{"listId":2,"name":null},{"listId":2,"name":null},{"listId":2,"name":""},{"listId":4,"name":"Item 771"},{"listId":2,"name":""}]
This is the code that I am using to displaying all my json data in textview
for(Map.Entry entry: data.entrySet())
{ textView.append(entry.getKey()+ " Value:" +entry.getValue() +"\n");}
I if understand correctly, you have a List<Post> posts that you want to sort out ? Why don't you sort the posts as you need and save them accordingly? You could just remove the post from your list if their name are null or ""
Related
I'd quickly explain what's going on in the JSON data above;
I have a table called messages, with some messages having a common message_id column. I grouped the messages by message_id. the boxes in red are the message_id's which have children
Now onto the question;
is it possible to access the children of the various arrays of message_id, without actually using the message_id string?
i.e iterate over the arrays
while (i < array.length) {
array[i]
}
if it's possible how can I do it?
Below is how I currently get the first array from the data object using the array id exactly
val jsonObject = JSONObject(response)
if (!jsonObject.getBoolean("error")) {
//getting data array from json response object
val dataObject = jsonObject.getJSONObject("data")
Log.i("MessageFragment", "[][] data array " + dataObject)
val array = dataObject.getJSONArray("NzbyxhmodN")
var i = 0
while (i < array.length()) {
//getting wallet object from json array
val message = array.getJSONObject(i)
//adding the wallet to wallet list
messageList!!.add(Message(
message.getInt("id"),
message.getInt("sender_id"),
message.getInt("receiver_id"),
message.getString("subject"),
message.getString("message"),
message.getString("message_id"),
message.getString("timestamp"),
message.getBoolean("isRead")
))
i++
}
I want to get the arrays without using the name i.e ("NzbyxhmodN")
Unfortunately, you cannot model without knowing the key value.
In such cases, I use this approach. It will be useful to you.
// data -> server json response
Iterator keys = data.keys();
while(keys.hasNext()) {
// random key
String key = (String)keys.next();
// and value...
JSONArray value = data.getJSONArray(key);
}
I am trying to learn retrofit and I have made successful attempts at posting data and now I am trying to retrieve JSON array which looks as follows:
{
"result": "success",
"message": "All Questions Have Been Selected",
"question": {
"all_question_ids": ["1","2","3"]
}
}
I am using the following getter
public ArrayList getAll_question_ids(){
return all_question_ids;
}
I am retrieving using Retrofit as follows
if (resp.getResult().equals(Constants.SUCCESS)) {
SharedPreferences.Editor editor = pref.edit();
Log.d("Question_IDs", "getAllQuestionID() = " + response.body().getQuestion().getAll_question_ids() );
editor.putString(Constants.All_QUESTION_IDS,((resp.getQuestion().getAll_question_ids().toString())));
editor.apply();
}
progress.setVisibility(View.INVISIBLE);
It is here that I am stuck, as I am retrieving the array ok but I am unsure how to loop out the Array which is now stored in Shared Preferences.
When I place a toast to show me how the IDs are coming across, my toast confirms the data as [1,2,3]
The goal is to add a dynamic button and the individual ID, i.e button 1, button 2 etc every-time the loop is iterated.
I have tried the following:
String questionNumber = pref.getString(Constants.All_QUESTION_IDS, "");
for (int i =0; i < questionNumber.length(); i++) {
try {
/*Dynamically create new Button which includes the question name
*/
AppCompatButton btn_question = new AppCompatButton(getActivity());
/*LayoutParams (int width, int height,float weight)
As LayoutParams is defaulted in px, I have called a method called dpToPX to make sure
the dynamically added EditText is the same size on all devices.
*/
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dpToPx(280), dpToPx(45), 1);
btn_question.setBackgroundColor(Color.parseColor("#3B5998"));
btn_question.setTextColor(Color.WHITE);
// btn_question.setText(String.valueOf(x));
btn_question.setText("Question "+ pref.getString(Constants.All_QUESTION_IDS,""));
btn_question.setGravity(Gravity.CENTER);
//generate unique ID for each new EditText dynamically created
View.generateViewId();
//Log.d("TEST VALUE", "Question1 generated ID = " + btn_question.generateViewId());
params.setMargins(0, dpToPx(10), 0, dpToPx(10));
btn_question.setPadding(0, 0, 0, 0);
btn_question.setLayoutParams(params);
allEds.add(btn_question);
mLayout.addView(btn_question);
} catch (Exception e) {
Log.d(TAG, "Failed to create new edit text");
}
}
However the above is adding the value as it appears in the array e.g [1,2,3] which is obviously not what I want.
I have added a photo in case my explanation isn't clear. I want a button with 1 number added to it each time the loop iterates but I am unable to figure this out.
I have looked through lots of resource but cannot find an answer that is relevant to my problem, although, if there is, I am not familiar enough to recognise a similar issue.
If someone can offer some assistance, I would appreciate it!
When you call editor.putString(Constants.All_QUESTION_IDS,((SOMETHING.toString())));, what is actually stored depends on the implementation of the toString method in the type of SOMETHING (in this case String[]). So avoid doing that. Instead, since you're already using Gson or Jackson (or others), store the question_idsas JSON:
final String jsonIds = gson.toJson (resp.getQuestion().getAll_question_ids());
editor.putString(Constants.All_QUESTION_IDS, jsonIds);
Your actual stored value no longer depends on the implementation of something that you don't control (String[].toString). It is a valid JSON array and regardless of what tool/library you use to read it back, it's valid.
Now, to read back the stored data:
final String storedJson = pref.getString(Constants.All_QUESTION_IDS, null);
if (null == storedJson) {
// TODO: No question ids found
}
final String[] ids = gson.fromJson (storedJson, String[].class);
for (int i = 0; i < ids.length; i++) {
// make your buttons
}
This is a problem of saving and then reading out a List of items (in this case, String instances).
You've chosen to save the list by calling editor.putString() with a value of getAll_question_ids().toString(). That toString() call is going to return a string representation of your list, or, in other words, a String instance with the value [1, 2, 3]. At this point, you no longer have a List proper, but a String that looks like a list.
This is all technically fine, but it means you have to take this into account when you're trying to read out that list.
You've written this to read the list back out:
String questionNumber = pref.getString(Constants.All_QUESTION_IDS, "");
Once this line executes, questionNumber will be a String instance with the value [1, 2, 3]. Again, this is fine, but now we come to the key point: we have to convert this String back into a List.
If you know for sure that the values in this list won't have commas in them, you can do it easily:
Trim the braces off the string using substring()
Create a String[] using split()
Convert your array to a list using Arrays.asList() (you could even skip this step since iterating over an array is just as easy as iterating over a list)
Put that together and you get:
String questionNumber = pref.getString(Constants.All_QUESTION_IDS, "");
questionNumber = questionNumber.substring(1, questionNumber.length() - 1);
String[] array = questionNumber.split(", ");
List list = Arrays.asList(array);
At this point, you can iterate over your array or list:
for (String value : list) {
...
btn_question.setText("Question " + value);
...
}
I think this problem is trivial, but I am not advanced in programming. I have problem with displaying Json data to TextView
My Json file is like
{
"person":{
"firstName":"John",
"lastName":"Jankow",
"nick":"Jayjay"
}
...
}
another data from Json like address, id etc. displaying without problem, when I use
((TextView) findViewById(R.id.person)).setText("Person: " + json.optString("person"));
I get string "person":{
"firstName":"John",
"lastName":"Jankow",
"nick":"Jayjay"
}"
I've tried to do this using
((TextView) findViewById(R.id.person)).setText("Person: " + json.optString("firstName") + json.optString("lastName"));
but the result is empty TextView.
Question ==> Is there any method to handle this data and display correctly like substring or something like this?
do this
JSONObject person = json.getJSONObject("person");
((TextView) findViewById(R.id.person)).setText("Person: " + person.getString("firstName") + person.getString("lastName"));
Not entirely sure if this helps but see this.
JSONObject person = jsonObj.getJSONObject("person");
String firstName = person.getString("firstName");
String lastName = person.getString("lastName");
Use strings in an awesome way.
textView.setText(firstName);
I wrote an Android App that pulls data from a MySql Database on a remote web server. The information is parsed and displayed in a listview. The listview also displays images which could slow down the activity. I was wondering how I could only display items 0-9, then when you click a button it will display 10-19, and so on. I can do it in VB using "do until" but as far as android/java, I am kind of lost. Any help would be appreciated.
Below is the class where I need to implement it. I believe I would need to add an Integer to keep count and implement a form of "DO UNTIL" before I loop through the array and add a count to the "Integer" but I am not sure how to go about it here.
class ProductQuery extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... file_url) {
// TODO Auto-generated method stub
try{
//Settings to send to PHP
List<NameValuePair> settings = new ArrayList<NameValuePair>();
//Adding Search Criteria(Keyword) to settings
settings.add(new BasicNameValuePair("product", product));
//Getting JSON result from request
JSONObject jObject = jParser.makeHttpRequest(url_to_php, "GET", settings);
//Display JSON in LogCat
Log.d("Product Search", jObject.toString());
//Get Result
int result = jObject.getInt(KEY_RESULT);
//If Result Equals 1 then
if(result==1){
//Getting the KEY_PRODUCTS
products = jObject.getJSONArray(KEY_PRODUCTS);
//Loop through Array
for(int i = 0; i < products.length();i++){
JSONObject x = products.getJSONObject(i);
String proPid = x.getString(KEY_PRODID);
String name = x.getString(KEY_NAME);
String price = x.getString(KEY_PRICE);
String desc = x.getString(KEY_DESCRIPTION);
String img = x.getString(KEY_IMAGE);
// creating new HashMap
HashMap<String, String> hmap = new HashMap<String, String>();
hmap.put(KEY_PRODID, proPid);
hmap.put(KEY_NAME, name);
hmap.put(KEY_PRICE, price);
hmap.put(KEY_DESCRIPTION, desc);
hmap.put(KEY_IMAGE, img);
//Hash to ArrayList
myproducts.add(hmap);
}
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
Instead of making pagination in the app, you should leave this to the server.
On your server, you should change the way you receive requests, so that when you call your server, you post a start index to fetch rows from and how many rows you want fetched for each request.
So the url to the server could look like this:
http://example.com/myjsonrequest.php?startindex=10&numofrows=10
In your PHP select statement on your server, you change it so it selects only the rows you need, like so:
SELECT * FROM my_table LIMIT $startindex, $numofrows;
Remember to check for SQL injections of course.
This way, you only fetch the data you actually want instead of fetching all the data in one go. Remember, your app is on a mobile OS, with a somewhat volatile internet connection sometimes, so if the data you're returning is growing, it wouldn't be nice from a user-perspective to sit and wait for all the data to load, especially when some of it, isn't needed yet.
For instance if you get let's say 1000 rows of data returned, that would take a while to fetch over a mobile internet connection.
After you receive the JSonObject with only a limited amount of entries, you can now parse it without keeping track of how many entries are returned.
Inside your Android app, all you need to keep track of is what index in the database, the user has seen so far and then increment this counter every time the user fetches a new page.
I want to parse my Json array dynamically. and want to get array of KEYS for each element under jsonarray. i an getting this through iterator. but not getting the sequeance as per the output json formate.
my JSON Formate :
{
"result": "Success",
"AlertDetails": [
{
"ShipmentNumber": "SHP34",
"Customer": "BEST",
"DateCreated": "2012-08-29T04:59:18Z"
"CustomerName": "BEST"
},
{
"ShipmentNumber": "SHP22",
"Customer": "BEST",
"DateCreated": "2012-08-29T05:34:18Z"
"CustomerName": "Jelly"
}
]
}
here is My Code :
JSONArray array = jsonobject.getJSONArray("AlertDetails");
JSONObject keyarray = array.getJSONObject(0);
Iterator temp = keyarray.keys();
while (temp.hasNext()) {
String curentkey = (String) temp.next();
KEYS.add(curentkey);
}
Log.d("Parsing Json class", " ---- KEYS---- " + KEYS);
What i am getting in logcate output:
---- KEYS---- [DateCreated,CustomerName, Customer, ShipmentNumber]
What i want :
---- KEYS---- [ShipmentNumber, Customer, DateCreated,CustomerName]
The JSONObject documentation (link: http://developer.android.com/reference/org/json/JSONObject.html) has the following description for the keys() function:
public Iterator keys ()
Since: API Level 1
Returns an iterator of the String names in this object. The returned
iterator supports remove, which will remove the corresponding mapping
from this object. If this object is modified after the iterator is
returned, the iterator's behavior is undefined. The order of the keys
is undefined.
So you may get the keys but the order is undefined. You may use any of the sorting algorithms if you want the keys in any particular order.
EDIT
Since you are unaware of the order of KEYS you are getting from the WS, after receiving the data you may show the details on screen in an ordered format . After building the arraylist KEYS, you may sort it alphabetically using the following:
Collections.sort(KEYS);
This will order the Strings in the KEYS arraylist according to its natural ordering (which is alphabetically).
I just come to know when I press ctlr+space bar, in which its clearly written that behavior of the keys is undefined, orders is not maintain by keys.
Arun George said# correctly that you have to use any sorting method to achieve your goal.
and for sorting may be this link will help you.
Use GSON library from google. It has a a lot of setting to read/create/parse json array and json objects. I didn't test it to find the solution, but I think it's very simple and full featured tool and can solve the problem.
Use different library to parse json dynamically.
Below I wrote a piece of code based on Jackson JSON Processor, which is the best JSON library in my opinion
public void test() throws IOException {
String str = "{\n" +
" \"result\": \"Success\",\n" +
" \"AlertDetails\": [\n" +
" {\n" +
" \"ShipmentNumber\": \"SHP34\",\n" +
" \"Customer\": \"BEST\",\n" +
" \"DateCreated\": \"2012-08-29T04:59:18Z\",\n" +
" \"CustomerName\": \"BEST\"\n" +
" }\n" +
" ]\n" +
"}";
JsonFactory factory = new JsonFactory();
JsonParser jsonParser = factory.createJsonParser(str);
JsonToken jsonToken;
SerializedString alertDetails = new SerializedString("AlertDetails");
while (!jsonParser.nextFieldName(alertDetails)) { /* move to AlertDetails field */ }
jsonParser.nextToken(); // skip [ start array
jsonParser.nextToken(); // skip { start object
// until } end object
while ((jsonToken = jsonParser.nextToken()) != JsonToken.END_OBJECT) {
if (jsonToken == JsonToken.FIELD_NAME) {
System.out.println(jsonParser.getCurrentName());
}
}
}
It simply prints out field names in the same order as in json:
ShipmentNumber
Customer
DateCreated
CustomerName
EDIT
Naturally you can use other libraries like gson etc. But remember, as is written on json.org, that:
An object is an unordered set of name/value pairs.
and the order of keys depends on implementation and might vary in each request.
There is also the method names();
Returns an array containing the string names in this object.
Edit: returns names in undefined order. Suggestions: parse it on your own