Getting an inner bundle from a bigger bundle in Android - android

I have a function in my Android code where I get a bundle as input:
void f(Bundle data)
This data is actually in the form of a json. Suppose it is in the following format:
{"a":"x", "b":"y", "content":{"a1":"x1", "b1":"y1"}}
In such cases, if I want to get the value of a, or b, then I would need to do String a = data.getString("a"); which would fetch me the string "x". Similarly, String content = data.getString("content") would return me the string {"a1":"x1", "b1":"y1"}}. But I cannot figure out how to get the specific values inside content itself. Is there any way by which I can get content as another bundle just like data so that I can get the values inside it by doing content.getString("a1") or something like that. Is that possible?

JSONObject jOBj = new JSONobject(data.getString("content"));
String a1 = jOBj.getString("x1");
String b1 = jOBj.getString("y1");
try this

To get value from bundle and create JSon object/ Hashmap
private void createFlatJSon(Bundle appRestrictions,JSONObject jsonObject) throws JSONException{
for (String key : appRestrictions.keySet()) {
if (appRestrictions.get(key) instanceof Bundle) {
createFlatJSon((Bundle) appRestrictions.get(key),jsonObject);
}else if (appRestrictions.get(key) instanceof Parcelable[]){
for (int i=0;i< ((Parcelable[]) appRestrictions.get(key)).length; i++){
createFlatJSon((Bundle)((Parcelable[]) appRestrictions.get(key))[i],jsonObject);
}
//Log.e("KEY skipped",appRestrictions.get(key).toString());
}else{
Log.e("KEY: ",key+" Value:"+appRestrictions.get(key).toString());
jsonObject.put(key,appRestrictions.get(key).toString());
}
}
}

Related

How to set a JSONObject default string for a null value

I am passing data to a recycler view using JSON, which works perfectly.
The problem is this, I want to alter the fetched json data. Let's say the user doesn't upload a profile image, that means the database field for image would be blank and our json wont parse any data for data.
So I want to set to a deafault url string if image == null
Heres what ive tried
//traversing through all the object
for (int i = 0; i < array.length(); i++) {
//getting product object from json array
JSONObject allTime = array.getJSONObject(i);
//adding the product to product list
allTimeEarnersList.add(new LeaderProfile(
allTime.getInt("id"),
allTime.getString("image"),
allTime.getString("username"),
allTime.getInt("earnings")
));
//My attempt to set a default value
if(allTime.getString("image").equals(null)){
allTime.put("image", "https://10.0.0.0/uploads/blank.png");
}
}
This doesn't work, it doesn't alter the output at all.
It is obvious i'm not doing this right.
Please how can I go about this? what is the best way to achieve this?
You aren't putting the value back into the object after you use the .put in the JSON, to avoid blanks/null in an object it's recommended to have a default value in case of nulls in your initializer.
public LeaderProfile(int id, String image, String username, int earnings) {
this.id = id;
if(image.equals("") || image.equals(null) ){
this.image = "defaulturl.png";
}else{
this.image = image;
}
this.username = username;
this.earnings = earnings;
}
Try this code block
if(allTime.getString("image") != null){
//set imageview glide or picasso
}else{
//set image view glide or picasso but R.drawable.empty_avatar
}

Parse JSON using amirdew/JSON library

I'm using amirdew/JSON library, which you can find here to parse my string to JSON.
The string I retrieved is this: https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=Portugal
This is the code I have at the moment, and it is not working and I believe that it is because of the keys...
public void ParseJson (String json){
JSON json2 = new JSON(json);
String firstTag = json2.key("query").key("pages").key("extract").stringValue();
txtInfo = findViewById(R.id.txtInfo);
txtInfo.setText(firstTag);
}
The firstTag variable is null because it can't retrieve any value. I want to retrieve the text inside "extracts". How can I do it? What keys do I need?
I suggest you to use the JSONObject which is already inside the SDK. You would use it like this:
String input = "..."; // your input
JSONObject obj = new JSONObject(input);
Strings extracts = obj.getJSONObject("query").getJSONObject("pages").getJSONObject("23033").getString("extract");

Pass two bundles to same activity

I have a list of json array response with multiple userinformation. Created a bundle and successfully passed it to next activity. Created another bundle with user selected date and time.But no luck to second bundle to the same activity because i can be able to pass only one bundle to same activity.
My actual problem is how to pass second bundle in putExtras to same activity
Json Response
{
"userinfo": [
{
"address": "Tambaram",
"name": "Vishranthi"
},
{
"address": "Medavakkam",
"name": "Sophia"
},
]
}
Bundle creation code:
JSONArray infoarray = obj.getJSONArray("Info");
Bundle h = new Bundle();
for (int i = 0; i < infoarray.length(); i++) {
Bundle b = new Bundle();
JSONObject infoobject = infoarray.getJSONObject(i);
String name = infoobject.getString("name");
String address = infoobject.getString("address");
b.putString("name", name);
b.putString("address", address);
h.putBundle(Integer.toString(i), b);
System.out.println(b);
}
Intent i = new Intent(context, Secondpage.class);
Bundle d=new Bundle();
d.putString("date", text1);
d.putString("time", text2);
i.putExtras(h);
System.out.println(h);
context.startActivity(i);
if you want to put two bundles into your intent you have to use
Intent putExtra (String name,
Bundle value)
something like this:
Intent i = new Intent(context, Secondpage.class);
i.putExtra("bundleH", h);
i.putExtra("bundleD", d);
ref
instead of create another Bundle to the date and time use the same one
You cannot, so the easiest solution would be to pass the json youre parsing into the second activity and the values you want on the second bundle as primitives, then on the second activity parse json into primitive data and retrieve date & time.
You don't need to deserialize a JSONObject or JSONArray, just put it in Bundle as String.
Bundle bundle = new Bundle();
bundle.putString("MyBundle", infoarray.toString());
So at next Activity, get the JSONArray
JSONArray newJArray = new JSONArray(bundle.getString("MyBundle",""));
A little tip: Avoid declare variables inside loops to avoid memory leaks.
I think you should change the approach a bit:
do this in your first activity your you have the json array
Intent i = new Intent(context, Secondpage.class);
i.putExtra("userinfo", infoarray.toString());
and in your second activity do the rest code
if (getIntent().getExtras() != null && getIntent().getExtras().containsKey("userinfo")) {
try {
JSONArray infoarray = new JSONArray(getIntent().getExtras().getString("userinfo"));
for (int i = 0; i < infoarray.length(); i++) {
]
JSONObject infoobject = infoarray.getJSONObject(i);
String name = infoobject.getString("name");
String address = infoobject.getString("address");
//your code parse user list
}
} catch (JSONException e)
}

Parsing JSON then adding multiple strings to an ArrayList

Currently working on an app that takes results from a search, parses the JSON object returned, and then adds the resulting pieces into a few ArrayLists within a class created called VenueList.
Here is the method that receives the results from the service and parses the JSON:
private static List<String> getResultsFromJson(String json) {
ArrayList<String> resultList = new ArrayList<String>();
try {
JSONObject resultsWrapper = (JSONObject) new JSONTokener(json).nextValue();
JSONArray results = resultsWrapper.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
resultList.add(result.getString("text"));
}
}
catch (JSONException e) {
Log.e(TAG, "Failed to parse JSON.", e);
}
return resultList;
}
What results of this becomes a List variable call mResults (to clarify: mResults = getResultsFromJson(restResult);. That is then used, among other places, in the following loop that puts the results into an ArrayAdapter that is used for displaying them in a ListFragment:
for (String result : mResults) {
VenueList.addVenue(result, "HELLO WORLD");
adapter.add(result);
}
I also add the result to a class called VenueList that manages the results and makes them accessible for multiple views. It essentially just holds multiple ArrayLists that hold different types of details for each venue returned in the search. The method I use to add a venue to VenueList is below (and you can see it used in the for loop above):
public static void addVenue(String name, String geo) {
venueNames.add(name);
venueGeos.add(geo);
}
I want the addVenue method to be able to take multiple arguments and update the VenueList class. Yet, when I call the addVenue method in the for loop, I can only pass it String result (from the parameters of the loop) and can't figure out how to pass it a second argument (which should also come from the JSON parsed by getResultsFromJson) so I've used "HELLO WORLD" as a placeholder for now.
I realize getResultsFromJson only has one list returned. I need to be able to take multiple elements from the JSON object that I parse, and then add them to VenueList in the right order.
So my questions are:
1) Given the getResultsFromJson method and the for loop, how can I use the addVenue() method as designed? How do I parse multiple elements from the JSON, and then add them to the VenueList at the same time? I plan on adding more arguments to it later on, but I assume if I can make it work with two, I can make it work with four or five.
2) If that's not possible, how should the getResultsFromJson, the for loop, and the addVenue method be redesigned to work properly together?
Please let me know if you need more detail or code - happy to provide. Thank you!
EDIT - Full VenueList class:
public class VenueList {
private static ArrayList<String> venueNames;
private static ArrayList<String> venueGeos;
public VenueList() {
venueNames = new ArrayList<String>();
venueGeos = new ArrayList<String>();
}
public static void addVenue(String name, String geo) {
venueNames.add(name);
venueGeos.add(geo);
}
public static String getVenueName(int position) {
return venueNames.get(position);
}
public static String getVenueGeo(int position) {
return venueGeos.get(position);
}
public static void clearList() {
venueNames.clear();
venueGeos.clear();
}
}
Clarification: I will have additional ArrayLists for each element of data that I want to store about a venue (phone number, address, etc etc)
1) I don't think methods getResultsFromJson(String json) and addVenue(String name, String geo) fit your needs.
2) I would consider rewriting method getResultsFromJson(String json) to something like this:
private static SortedMap<Integer, List<String>> getResultsFromJson(String json) {
Map<Integer, String> resultMap = new TreeMap<Integer, String>();
//...
return resultMap;
}
where the number of keys of your map should be equal to the number of objects you're extracting info, and each one of them will properly have their own list of items just in the right order you extract them.
With this approach you can certainly change your logic to something like this:
// grab your retuned map and get an entrySet, the just iterate trough it
SortedMap<Integer, String> result = returnedMap.entrySet();
for (Entry<Integer, String> result : entrySet) {
Integer key = result.getKey(); // use it if you need it
List<String> yourDesiredItems = result.getValue(); // explicitly shown to know how to get it
VenueList.addVenue(yourDesiredItems);
}
public static void addVenue(List<String> yourDesiredItems) {
// refactor here to iterate the items trough the list and save properly
//....
}
EDIT -- as you wish to avoid the go-between map i'm assuming you need nothing to return from the method
First i'm providing you with a solution to your requirements, then i'll provide you with some tips cause i see some things that could smplify your design.
To save VenueList things directly from getResultsFromJSON do something like this:
private static void getResultsFromJson(String json) {
try {
JSONObject resultsWrapper = (JSONObject) new JSONTokener(json).nextValue();
JSONArray results = resultsWrapper.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
//FOR EXAMPLE HERE IS WHERE YOU NEED TO EXTRACT INFO
String name = result.getString("name");
String geo = result.getString("geo");
// and then...
VenueList.addVenue(name, geo, ..., etc);
}
} catch (JSONException e) {
Log.e(TAG, "Failed to parse JSON.", e);
}
}
This implies that your addVenue method should know receive all params needed; as you can see this is just a way (that you can consider a workaround to your needs), however as i don't know all requirements that lead you to code this model, i will point to a few things you might consider:
1. If there's a reason for VenueList class to use everything static, consider doing this:
static{
venueNames = new ArrayList<String>();
venueGeos = new ArrayList<String>();
//....
}
private VenueList(){
}
This way you won't need to get an instance every time and also will avoid null pointer exceptions when doing VenueList.addVenue(...) without previous instantiation.
2. Instead of having an ArrayList for every characteristic in VenueList class consider defining a model object for a Venue like this:
public class Venue{
String name;
String geo;
//... etc
public Venue(){
}
// ... getters & setters
}
then if you need that VenueList class you will just have a list o Venue objects (List<Venue>), this means that instead of calling the method addVenue, you will first create a brand new instance of Venue class and will call the setter method of each characteristic, as an example of the refactored for loop from the workaround i provided you you'd be using something like this:
List<Venue> myListOfVenues = new ArrayList<Venue>();
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
// THIS WOULD REMAIN THE SAME TO EXTRACT INFO
String name = result.getString("name");
String geo = result.getString("geo");
// and then instead of calling VenueList.addVenue(name, geo, ..., etc)...
Venue v = new Venue();
v.setName(name);
v.setGeo(geo);
// ...etc
myListOfVenues.add(v);
}
// Once you're done, set that List to VenueList class
VenueList.setVenueList(myListOfVenues);
So VenueList class would now have a single property List<Venue> venueList; and would suffer minor tweeks on methods getVenueName, etc... and everything would be more readable... i hope this helps you to get another approach to solve your problem, if i still don't make my point let me know and i'll try to help you out...

how to be easier to analyse the json

i want to analyse the json just like:
[{"id":"ssq","name":"双色球","term":"2010092","date":"2010-08-12 19:15","numbers":{"normal":"3,13,19,27,28,30","special":"2"},"jackpot":"30000000"},{"id":"3d","name":"3D","term":"2010216","date":"2010-08-12 19:55","numbers":{"normal":"6,8,8"},"jackpot":"-"},{"id":"qlc","name":"七乐彩","term":"2010093","date":"2010-08-11 20:45","numbers":{"normal":"08,09,10,11,16,21,27","special":"26"},"jackpot":"0"},{"id":"dfljy","name":"东方6+1","term":"2010093","date":"2010-08-14 18:30","numbers":{"normal":"4,1,3,9,7,2","special":"羊"},"jackpot":"12866531"},{"id":"swxw","name":"15选5","term":"2010217","date":"2010-08-12 18:45","numbers":{"normal":"1,3,5,13,15"},"jackpot":"5693612"},{"id":"ssl","name":"时时乐","term":"20100811-23","date":"2010-08-12 10:27","numbers":{"normal":"6,7,1"},"jackpot":"-"},{"id":"klsf","name":"快乐十分","term":"201021649","date":"2010-08-11 22:00","numbers":{"normal":"5,11,12,14,20"},"jackpot":"-"},{"id":"klsc","name":"快乐双彩","term":"2010215","date":"2010-08-10 21:25","numbers":{"normal":"12,23,10,15,7,3","special":"11"} ,"jackpot":"198059"}]
i want to gain all of them,but the data is so many,so whether i need to create 8 kinds of class to store the data,so to be easier to use.thanks!
To add to cfei's response, one thing that I've done when processing JSON responses from Flickr, is create a new class particularly for that type of object.
So for yours, just playing it by ear, something like the below:
public class Lottery() {
private JSONObject json;
private String id;
private String name;
private String term;
private String date;
private String norm_numbers;
private String spec_numbers;
private String jackpot;
public Lottery(JSONObject json) {
this.json = json;
}
public void setId()
{
try {
id = json.getString("id");
} catch (JSONException e) {
id = "";
}
}
//additional getters and setters, etc.
}
This way, you can make an array of objects, and access the fields like so:
//...get a JSONObject from the array...
Lottery lottery = new Lottery(json);
Log.v("ID", lottery.id);
Log.v("Name", lottery.name);
and so on.
Do you mean that you want to iterate through each of the eight JSONObjects in this JSONArray? You need to create a JSONArray object with the input string you posed above (let's call it "response", as used below) and then iterate through the array to get each JSONObject it contains. For example:
JSONArray array = new JSONArray(response);
for(int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
// do something with obj
// example: to get the id for a particular object, use obj.getString("id")
Log.i("Example", "the id is"+obj.getString("id"));
}

Categories

Resources