Related
I am building an android app that needs to download and synchronise with an online database, I am sending my query from the app to a php page which returns the relevant rows from a database in JSON format.
can someone please tell me the best way to iterate through a JSON array?
I receive an array of objects:
[{json object},{json object},{json object}]
What is the simplest piece of code I could use to access the JSONObjects in the array?
EDIT: now that I think of it the method I used to iterate the loop was:
for (String row: json){
id = row.getInt("id");
name = row.getString("name");
password = row.getString("password");
}
So I guess I had was somehow able to turn the returned Json into and iterable array. Any Ideas how I could achieve this?
I apologise for my vaguness but I had this working from an example I found on the web and have since been unable to find it.
I think this code is short and clear:
int id;
String name;
JSONArray array = new JSONArray(string_of_json_array);
for (int i = 0; i < array.length(); i++) {
JSONObject row = array.getJSONObject(i);
id = row.getInt("id");
name = row.getString("name");
}
Is that what you were looking for?
I have done it two different ways,
1.) make a Map
HashMap<String, String> applicationSettings = new HashMap<String,String>();
for(int i=0; i<settings.length(); i++){
String value = settings.getJSONObject(i).getString("value");
String name = settings.getJSONObject(i).getString("name");
applicationSettings.put(name, value);
}
2.) make a JSONArray of names
JSONArray names = json.names();
JSONArray values = json.toJSONArray(names);
for(int i=0; i<values.length(); i++){
if (names.getString(i).equals("description")){
setDescription(values.getString(i));
}
else if (names.getString(i).equals("expiryDate")){
String dateString = values.getString(i);
setExpiryDate(stringToDateHelper(dateString));
}
else if (names.getString(i).equals("id")){
setId(values.getLong(i));
}
else if (names.getString(i).equals("offerCode")){
setOfferCode(values.getString(i));
}
else if (names.getString(i).equals("startDate")){
String dateString = values.getString(i);
setStartDate(stringToDateHelper(dateString));
}
else if (names.getString(i).equals("title")){
setTitle(values.getString(i));
}
}
Unfortunately , JSONArray doesn't support foreach statements, like:
for(JSONObject someObj : someJsonArray) {
// do something about someObj
....
....
}
When I tried #vipw's suggestion, I was faced with this exception:
The method getJSONObject(int) is undefined for the type JSONArray
This worked for me instead:
int myJsonArraySize = myJsonArray.size();
for (int i = 0; i < myJsonArraySize; i++) {
JSONObject myJsonObject = (JSONObject) myJsonArray.get(i);
// Do whatever you have to do to myJsonObject...
}
If you're using the JSON.org Java implementation, which is open source, you can just make JSONArray implement the Iterable interface and add the following method to the class:
#Override
public Iterator iterator() {
return this.myArrayList.iterator();
}
This will make all instances of JSONArray iterable, meaning that the for (Object foo : bar) syntax will now work with it (note that foo has to be an Object, because JSONArrays do not have a declared type). All this works because the JSONArray class is backed by a simple ArrayList, which is already iterable. I imagine that other open source implementations would be just as easy to change.
On Arrays, look for:
JSONArray menuitemArray = popupObject.getJSONArray("menuitem");
You are using the same Cast object for every entry.
On each iteration you just changed the same object instead creating a new one.
This code should fix it:
JSONArray jCastArr = jObj.getJSONArray("abridged_cast");
ArrayList<Cast> castList= new ArrayList<Cast>();
for (int i=0; i < jCastArr.length(); i++) {
Cast person = new Cast(); // create a new object here
JSONObject jpersonObj = jCastArr.getJSONObject(i);
person.castId = (String) jpersonObj.getString("id");
person.castFullName = (String) jpersonObj.getString("name");
castList.add(person);
}
details.castList = castList;
While iterating over a JSON array (org.json.JSONArray, built into Android), watch out for null objects; for example, you may get "null" instead of a null string.
A check may look like:
s[i] = array.isNull(i) ? null : array.getString(i);
I am building an android app that needs to download and synchronise with an online database, I am sending my query from the app to a php page which returns the relevant rows from a database in JSON format.
can someone please tell me the best way to iterate through a JSON array?
I receive an array of objects:
[{json object},{json object},{json object}]
What is the simplest piece of code I could use to access the JSONObjects in the array?
EDIT: now that I think of it the method I used to iterate the loop was:
for (String row: json){
id = row.getInt("id");
name = row.getString("name");
password = row.getString("password");
}
So I guess I had was somehow able to turn the returned Json into and iterable array. Any Ideas how I could achieve this?
I apologise for my vaguness but I had this working from an example I found on the web and have since been unable to find it.
I think this code is short and clear:
int id;
String name;
JSONArray array = new JSONArray(string_of_json_array);
for (int i = 0; i < array.length(); i++) {
JSONObject row = array.getJSONObject(i);
id = row.getInt("id");
name = row.getString("name");
}
Is that what you were looking for?
I have done it two different ways,
1.) make a Map
HashMap<String, String> applicationSettings = new HashMap<String,String>();
for(int i=0; i<settings.length(); i++){
String value = settings.getJSONObject(i).getString("value");
String name = settings.getJSONObject(i).getString("name");
applicationSettings.put(name, value);
}
2.) make a JSONArray of names
JSONArray names = json.names();
JSONArray values = json.toJSONArray(names);
for(int i=0; i<values.length(); i++){
if (names.getString(i).equals("description")){
setDescription(values.getString(i));
}
else if (names.getString(i).equals("expiryDate")){
String dateString = values.getString(i);
setExpiryDate(stringToDateHelper(dateString));
}
else if (names.getString(i).equals("id")){
setId(values.getLong(i));
}
else if (names.getString(i).equals("offerCode")){
setOfferCode(values.getString(i));
}
else if (names.getString(i).equals("startDate")){
String dateString = values.getString(i);
setStartDate(stringToDateHelper(dateString));
}
else if (names.getString(i).equals("title")){
setTitle(values.getString(i));
}
}
Unfortunately , JSONArray doesn't support foreach statements, like:
for(JSONObject someObj : someJsonArray) {
// do something about someObj
....
....
}
When I tried #vipw's suggestion, I was faced with this exception:
The method getJSONObject(int) is undefined for the type JSONArray
This worked for me instead:
int myJsonArraySize = myJsonArray.size();
for (int i = 0; i < myJsonArraySize; i++) {
JSONObject myJsonObject = (JSONObject) myJsonArray.get(i);
// Do whatever you have to do to myJsonObject...
}
If you're using the JSON.org Java implementation, which is open source, you can just make JSONArray implement the Iterable interface and add the following method to the class:
#Override
public Iterator iterator() {
return this.myArrayList.iterator();
}
This will make all instances of JSONArray iterable, meaning that the for (Object foo : bar) syntax will now work with it (note that foo has to be an Object, because JSONArrays do not have a declared type). All this works because the JSONArray class is backed by a simple ArrayList, which is already iterable. I imagine that other open source implementations would be just as easy to change.
On Arrays, look for:
JSONArray menuitemArray = popupObject.getJSONArray("menuitem");
You are using the same Cast object for every entry.
On each iteration you just changed the same object instead creating a new one.
This code should fix it:
JSONArray jCastArr = jObj.getJSONArray("abridged_cast");
ArrayList<Cast> castList= new ArrayList<Cast>();
for (int i=0; i < jCastArr.length(); i++) {
Cast person = new Cast(); // create a new object here
JSONObject jpersonObj = jCastArr.getJSONObject(i);
person.castId = (String) jpersonObj.getString("id");
person.castFullName = (String) jpersonObj.getString("name");
castList.add(person);
}
details.castList = castList;
While iterating over a JSON array (org.json.JSONArray, built into Android), watch out for null objects; for example, you may get "null" instead of a null string.
A check may look like:
s[i] = array.isNull(i) ? null : array.getString(i);
I need to create constant json string or a json sorted on keys. What do I mean by constant json string? Please look into following code sample, which I created.
My Code 1:
public class GsonTest
{
class DataObject {
private int data1 = 100;
private String data2 = "hello";
}
public static void main(String[] args)
{
GsonTest obj=new GsonTest();
DataObject obj2 = obj.new DataObject();
Gson gson = new Gson();
String json = gson.toJson(obj2);
System.out.println(json);
}
}
Output 1:
{"data1":100,"data2":"hello"}
My Code 2:
public class GsonTest
{
class DataObject {
private String data2 = "hello";
private int data1 = 100;
}
public static void main(String[] args)
{
GsonTest obj=new GsonTest();
DataObject obj2 = obj.new DataObject();
Gson gson = new Gson();
String json = gson.toJson(obj2);
System.out.println(json);
}
}
Output 2:
{"data2":"hello","data1":100}
If you see, if I switch variables (data1 & data2 in DataObject class), I get different json. My objective to get same json, even if somebody changes position of the class variables. I get it when somebody adds new variables, json would change. But json shouldn't change when variables are moved around. So, my objective is to get standard json, possibly in sorted keys order for same class. If there is nested json, then it should be sorted in the nested structure.
Expected output on run of both the codes:
{"data1":100,"data2":"hello"} //sorted on keys!! Here keys are data1 & data2
I understand, I need to change something in String json = gson.toJson(obj2); line, but what do I have to do?
Why I need them to be order?
I need to encode the json string and then pass it to another function. If I change the order of keys, even though value remain intact, the encoded value will change. I want to avoid that.
First of all, the keys of a json object are unordered by definition, see http://json.org/.
If you merely want a json string with ordered keys, you can try deserializing your json into a sorted map, and then serialize the map in order to get the sorted-by-key json string.
GsonTest obj=new GsonTest();
DataObject obj2 = new DataObject();
Gson gson = new Gson();
String json = gson.toJson(obj2);
TreeMap<String, Object> map = gson.fromJson(json, TreeMap.class);
String sortedJson = gson.toJson(map);
Like others have mentioned that by design JSON is not supposed to have sorted keys in itself. You can also come up with a recursive solution to do it. I won't say my solution is very efficient but it does the intended job. Please have a look at the following piece of code.
private static JsonObject sortAndGet(JsonObject jsonObject) {
List<String> keySet = jsonObject.keySet().stream().sorted().collect(Collectors.toList());
JsonObject temp = new JsonObject();
for (String key : keySet) {
JsonElement ele = jsonObject.get(key);
if (ele.isJsonObject()) {
ele = sortAndGet(ele.getAsJsonObject());
temp.add(key, ele);
} else if (ele.isJsonArray()) {
temp.add(key, ele.getAsJsonArray());
} else
temp.add(key, ele.getAsJsonPrimitive());
}
return temp;
}
Input:
{"c":"dhoni","a":"mahendra","b":"singh","d":{"c":"tendulkar","b":"ramesh","a":"sachin"}}
Output:
{"a":"mahendra","b":"singh","c":"dhoni","d":{"a":"sachin","b":"ramesh","c":"tendulkar"}}
Perhaps a work around is for your class wrap a TreeMap which maintains sort order of the keys. You can add getters and setters for convenience. When you gson the TreeMap, you'll get ordered keys.
In my current android program I want to transfer very large size of key value pair of integers to server using json string. Below are the two approaches, I just want to know which one is a best approach and why. I am going to run this program in android phones so I am worrying about creating lots of objects.
Approach 1.
public class DataBean {
int dataKey = 0;
int dataValue = 0;
}
ArrayList<DataBean> dataBeans = new ArrayList<DataBean>();
for(some condition){
int dataKey = //Some operations to get Key
int dataValue = //Some operations to get Value
DataBean dataBean = new DataBean();
dataBean.dataKey = dataKey;
dataBean.dataValue = dataValue;
dataBeans.add(dataBean);
}
//Here some JSON library like Jackson Jar to convert ArrayList<DataBean> to JSON String
Approach 2.
StringBuilder stringBuilder = new StringBuilder();
for(some condition){
int dataKey = //Some operations to get Key
int dataValue = //Some operations to get Key
stringBuilder.append("{"+dataKey+","+dataValue+"},"); //Generate Direct JSON String
}
//Here direct JSON
String JSON = stringBuilder.toString();
I want to know if is it possible to Store a String variable on a String array?
I cant explain it well but here is what i do:
String st1 = "",st2 = "",st3 = "",st4 = "";
String[] str = {st1,st2,st3,st4};
Unfortunately when i use for loop the str gets the value of st1 and st2 and st3 ans st4 not the variable it self..
This is what i want to do exactly on my mind..
Whenever a have a String array for example:
String[] containsValue = { "hi", "hello", "there" };
String strHi, strHello, strThere;
String[] getContainsValue = { strHi, strHello, strThere };
for (int x = 0; x < getContainsValue.length; x++) {
getContainsValue[x] = containsValue[x];
}
The value of:
strHi = "hi"
strHello = "hello"
strThere = "there";
Basically i want to transfer that value of containsValue[] to 3 String which is strHi, strHello, strThere that are stored in getContainsValue[]. Then use for loop to asign value to them came from containsValue[].
Is this posible? If so then can you give me some format how to do it? thanks..
You can use Map<K,V>.
Map<String,String> map=new HashMap<String,String>();
map.put("strHi","hi");
map.put("strHello","hello");
map.put("strThere","there");
System.out.println(map.get("strHello"));
You can use enum class as the Array needed :
public enum EnumModifE {
str1("1"), str2("2"), str3("3");
String value;
EnumModifE(final String s) {
this.value = s;
}
public void setValue(final String s) {
this.value = s;
}
}
public class EnumModifM {
public static void main(final String[] args) {
for (final EnumModifE eme : EnumModifE.values()) {
System.out.println(eme + "\t" + eme.value);
}
EnumModifE.str1.setValue("Hello");
EnumModifE.str2.setValue("all");
EnumModifE.str3.setValue("[wo]men");
for (final EnumModifE eme : EnumModifE.values()) {
System.out.println(eme + "\t" + eme.value);
}
}
}
Output
str1 1
str2 2
str3 3
str1 Hello
str2 all
str3 [wo]men
See in Effective Java use of enum
The concept you are looking for is an "l-value". Briefly, when you are using a variable, are you using the value contained in the variable, or are you talking about the variable itself so that you can store something else into it? You want array that you're calling getContainsValue to have l-values for strHi, strHello, and strThere. Unfortunately there is no way to do this in Java. Initializing getContainsValue with strHi, strHello, and strThere uses the values of those variables, not their l-values.
Let's step back a bit and talk more about l-values vs values (sometimes, r-values). Consider the following code snippet:
int i = 17;
i = i + 1;
That second line is obviously not an equation; that would be nonsensical. Instead, it is an assignment. The meaning of i on the left and right sides of an assignment is different. On the right hand side, i means to use the value of that variable, in this case 17. On the left hand side, i means the variable itself, as a destination for storing values. Even though they look the same, the use of i on the right-hand side is for its value (more specifically, its r-value) and the use of i on the left-hand side is for its l-value.
In Java, there is no way to express the l-value of a variable in an array initializer, so what you're trying to do doesn't work. As others have pointed out, in other languages like C this is possible, by using the & (address-of) operator.
Since Java has limited ways of expressing l-values, usually the concept of "a place to store something into" is expressed via a reference to an object. One can then use this reference to store into fields of that object or to call methods on that object.
Suppose we have a class like this:
class MyContainer {
String str;
void setString(String s) { str = s; }
String getString() { return str; }
}
We could then rewrite your code to do something like the following:
String[] containsValue = { "hi", "hello", "there" };
MyContainer hiCont = new MyContainer();
MyContainer helloCont = new MyContainer();
MyContainer thereCont = new MyContainer();
MyContainer[] getContainsValue = { hiCont, helloCont, thereCont };
for (int x = 0; x < getContainsValue.length; x++) {
getContainsValue[x].setString(containsValue[x]);
}
Well you can use this.
Map<String,String> map = new HashMap<String,String>();
String[] str = {"hi","hello","there"};
for(int x = 0; x < str.lenght;x++){
map.put(str[x],"something you want to store");
}
Best thing may be use Map and store as key-Value pairs.
Map<String,String> myKVMap=new HashMap<String,String>();
myKVMap.put("strHi","value1");
myKVMap.put("strHello","value2");
myKVMap.put("strThere","value3");
This way you can eliminate all the variable name and value issues.
I think you should use Collection like Map.
Map is used to store data in the form of Key-Value Pairs.
Assume the Key is String and Value is a String too in your case.
Map<String, String> mp = new Map<String, String>();
mp.put("str1","Hi");
mp.put("str2","Hello");
You can iterate over it like the below.
for(Map.Entry<String, String> ar : mp.entrySet()){
System.out.println("Key: "+ar.getKey()+" :: "+"Value: "+ar.getValue());
}
Using a Map is a good idea. Another approach is to instantiate class variables, then assigning values will work.
public void testTransfer() {
String containsValue[] = { "hi", "hello", "there" };
Data strHi = new Data();
Data strHello = new Data();
Data strThere = new Data();
Data[] getContainsValue = { strHi, strHello, strThere };
for (int x = 0; x < getContainsValue.length; x++) {
getContainsValue[x].value = containsValue[x];
}
// print out
System.out.println(strHi.value);
System.out.println(strHello.value);
System.out.println(strThere.value);
}
class Data {
private String value;
}
There is no simple way to do what you want to do in Java. What you would need is the equivalent of the C / C++ address-of operator (&) ... or maybe Perl's ability to use a string as a variable name. Neither of these are supported in Java.
In theory, if the variables where instance variables, you could use reflection to access and update them. But the code to do this is messy, inefficient and fragile. And it won't work with local variables.
You would be better off looking for a different solution to the problem; e.g. use a Map, as other answers have suggested.
Or just settle for some clunky (but robust and reasonably efficient) code that uses a switch or series of if else if tests and the original variables.
If I am understanding your question, you want to be able to assign a regular String variable by looking it up in an array first and then making the assignment.
I agree with the other responders that if you are finding this approach necessary, it is probably ill-advised. But in the spirit of pure Q&A, here's the way:
interface StringAssigner {
void assign( String strValue );
}
// ...
String strHi, strHello, strThere;
StringAssigner[] asaGetContainsValue = {
new StringAssigner() { #Override public void assign( String strValue ) { strHi = strValue; } },
new StringAssigner() { #Override public void assign( String strValue ) { strHello = strValue; } },
new StringAssigner() { #Override public void assign( String strValue ) { strThere = strValue; } }
};
// ...
for (int x = 0; x < asaGetContainsValue.length; x++) {
asaGetContainsValue[x].assign( containsValue[x] );
}
Just say no.
I do agree with the other answers here that this feels like a workaround for something, but without knowing what that something is I cannot suggest anything better.
To answer the question, though: you could, however, wrap the string in simple class and store the object references of that class in your array and strHi, strHello, and strThere. This way even when you change the string property inside the class, the class object itself does not change so you will see the behavior you are looking for.
Or, you can use a HashMap as others have suggested. In your case if you still want to use the getContainsValue array, you can store the keys:
Map<String,String> map = new HashMap<String,String>();
map.put("strHi","");
map.put("strHello","");
map.put("strThere","");
String[] containsValue = { "hi", "hello", "there" };
String[] getContainsValue = { "strHi", "strHello", "strThere" };
for (int x = 0; x < getContainsValue.length; x++) {
map.put(getContainsValue[x], containsValue[x]);
}
Then, map.get("strHi") would return "hi" as you expect.