I try to get patient information, by sending an ID to the server. I expect the result to be a JSONObject, as only one patient corresponds with the ID. However, what i get is a JSONArray. I have tried to do getJSONObject(0), but it gives this error:
Index 0 out of range [0..0)
Why i is an Array and not an Object, and how do i deal with it?
This is my java code in the activity:
new HttpRequestTask(
"getPatientFull",
new String[]{"ID"},
new String[]{PatientID}, new HttpRequestTask.ResultReceiver() {
#Override
public void processResult(String apiFunctionName, JSONObject result) {
if (result != null) {
try {
if (result.has("error")) {
shorttoast("ERROR: " + result.getString("error") + "saving patient file");
} else {
if (result.has("patient_details")) {
patientName = result.getJSONArray("patient_details").getJSONObject(0).getString("NAME");
shorttoast(patientName);
}
}
} catch (JSONException ex) {
shorttoast("ERROR" + ex.getLocalizedMessage());
}
} else
shorttoast("Retreiving failed");
}
}).execute();
The PatientID is defined earlier in the code (it's an existing patient id).
and this is the php API function that was defined by my teacher:
app.post("/getPatientFull", function (req, res) {
pool.getConnection(function (err, connection) {
connection.query('SELECT * FROM PatientDossier WHERE PATIENT_ID=?',
[req.query.ID],
function (error, results, fields) {
if (error) {
res.status(403).json({"error": error.code});
} else {
res.status(200).json({patient_details:results});
}
});
connection.release();
});
});
The PHP function does not return a single object, it returns an array.
So, you should expect a JSONArray on the Android side.
As to why getJSONObject(0) is giving you an out-of-bounds error, I'm not sure.
Try using the debugger to look at the JSONArray, and see what's in it. It's possible that you searched for a patient id that's not in the database, and the PHP code returned an empty array. Your code should be checking that anyway.
It also looks like maybe "result" is a JSONObject containing the array, under the key "patient_details", in which case, you need to get the value of "patient_details" and index into that array. If you show us the JSON response, it would be easier to tell.
Related
I need to write a code which would convert JSON file to CSV. The problem is in a format that the CSV file should look like.
Input json:
{
"strings":{
"1level1":{
"1level2":{
"1label1":"1value1",
"1label2":"1value2"
}
},
"2level1":{
"2level2":{
"2level3":{
"2label1":"2value1"
},
"2label2":"2value2"
}
}
}
}
And this is expected csv file for this json:
Keys,Default
1level1.1level2.1label1,1value1
1level1.1level2.1label2,1value2
2level1.2level2.2level3.2label1,2value1
2level1.2level2.2label2,2value2
I was trying to go through JSON file using recursion but this didn't work for me because of rewriting JSON object on each iteration and code was working only till the first value. Are there any suggestions about how can it be done?
Note: have tried to use different JSON libraries, so for now can be used any of them
UPDATE #1:
Non-working code example I was trying to use to go through JSON tree:
public static void jsonToCsv() throws JSONException {
InputStream is = MainClass.class.getResourceAsStream("/fromJson.json");
JSONTokener jsonTokener = new JSONTokener(is);
JSONObject jsonObject = new JSONObject(jsonTokener);
stepInto(jsonObject);
}
private static void stepInto(JSONObject jsonObject) {
JSONObject object = jsonObject;
try {
Set < String > keySet = object.keySet();
for (String key: keySet) {
object = object.getJSONObject(key);
stepInto(object);
}
} catch (JSONException e) {
Set < String > keySet = object.keySet();
for (String key: keySet) {
System.out.println(object.get(key));
}
e.printStackTrace();
}
}
UPDATE #2:
Another issue is that I will never know the names of the JSON object and count of child objects (update JSON and CSV examples as well to make the image more clear). All that is known, that it will always start with strings object.
Library used:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
So found a solution by myself:
public static void jsonToCsv() throws JSONException, IOException {
InputStream is = MainClass.class.getResourceAsStream("/fromJson.json");
JSONTokener jsonTokener = new JSONTokener(is);
JSONObject jsonObject = new JSONObject(jsonTokener).getJSONObject("strings");
builder = new StringBuilder();
while (!jsonObject.isEmpty()) {
stepInto(jsonObject);
}
String[] lines = builder.toString().split("\n"); // builder lines are in reverse order from expected so this array is used to reverse them
FileWriter csvWriter = new FileWriter("src/main/resources/toCsv.csv");
csvWriter.append("Keys,Default (en_US)\n");
for (int i = lines.length - 1; i >= 0; i--) {
csvWriter.append(lines[i]).append("\n");
}
csvWriter.flush();
csvWriter.close();
}
private static void stepInto(JSONObject jsonObject) {
for (String key: jsonObject.keySet()) {
Object object = jsonObject.get(key);
if (object instanceof JSONObject) {
builder.append(key).append(".");
stepInto(jsonObject.getJSONObject(key));
} else {
builder.append(key).append(",").append(object).append("\n");
jsonObject.remove(key);
break;
}
if (jsonObject.getJSONObject(key).isEmpty()) {
jsonObject.remove(key);
}
break;
}
}
I think you just missed keeping track of your result, otherwise it looks good.
Let's say your result is a simple string. Then you have to concatenate all keys while traversing the json object until you reach a primitive value (like a number or a string).
(I am writing this out of my head, so please forgive me for incorrect syntax)
private static String stepInto(JSONObject jsonObject) { // we change "void" to "String" so we can record the results of each recursive "stepInto" call
//JSONObject object = jsonObject; // we don't need that. Both variables are the same object
String result ="";
try {
for (String key: jsonObject.keySet()) { // shorter version
Object object = jsonObject.get(key); // Attention! we get a simple Java Object
if(object instanceof JSONObject){
result+= key+"."+stepInto(jsonObject.getJSONObject(key)); // the recursive call, returning all keys concatenated to "level1.level2.level3" until we reach a primitive value
}
if(object instanceof JSONArray){
result+= key+", "+ ... // notice how we use the csv separator (comma) here, because we reached a value. For you to decide how you want to represent arrays
}
result+= key +", "+ object +"\n"; // here I am not sure. It may well be that you need to check if object is a String an Integer, Float or anything.
}
} catch (JSONException e) {
for (String key: jsonObject.keySet()) {
System.out.println(object.get(key));
}
e.printStackTrace();
result+= "\n"; // I added this fallback so your program can terminate even when an error occurs.
}
return result; // sorry, I forgot to accumulate all results and return them. So now we have only one actual "return" statement that will terminate the call and return all results.
}
As you can see, I didn't change much of your original method. The only difference is that now we keep track of the keys ("level1.level2...") for each recursive call.
EDIT
I added a +"\n"; so everytime we reach a value so we can terminate that "line".
AND more importantly, instead of returning everytime, I add the result of each call to a string, so we continue looping over the keys and concatenate all results. Each call of the method will return only once all keys are looped over. (sorry that missed that)
In your calling method you could print out the result, something like that:
JSONObject jsonObject = new JSONObject(jsonTokener);
String result = stepInto(jsonObject);
System.out.println(result);
My API response contains a blank array: []
how to validate?
For positive scenarios i have jsonarray and jsonobject . here am not sure how to validate the empty array.
public void ValidateEmptyArray() throws JSONException {
try {
if(responseJObject.isEmpty()) {
report.reportPassEvent("Validate cause attribute", "cause value is -"+ responseJObject.getString("cause"));
} else {
report.assertFailEvent("Validate cause attribute", "cause value is -"+ responseJObject.getString("cause")+
" And expected value is - "+cause);
}
} catch(Exception e) {
report.assertFailEvent("Validate cause attribute", "cause attribute is not present in the response");
}
}
What I want to do is at a particular index position change/replace a value inside a json array.After going through the documentation at http://www.json.org/javadoc/org/json/JSONArray.html I found out that jsonArray does not have a getIndex() method.In this situation how do I update my json array at a given index position.
This is the method that creates a json array in my android code.
private void createJsonArray() {
billType = (invEstSwitch.isChecked() ? textViewEstimate : textViewInvoice)
.getText().toString();
String invNumber = textViewInvNo.getText().toString();
String bcode = barCode.getText().toString();
String description = itemDesc.getText().toString();
String wt = weightLine.getText().toString();
String rateAmt = rateAmount.getText().toString();
String making = makingAmount.getText().toString();
String netr = netRate.getText().toString();
String iTotal = itemtotal.getText().toString();
String vatAmt = textViewVat.getText().toString();
String sumAmt = textViewSum.getText().toString();
String crtDate = textViewCurrentDate.getText().toString();
try {
jsonObject.put("custInfo", custSelected.toString());
jsonObject.put("invoiceNo", invNumber);
jsonObject.put("barcode", bcode);
jsonObject.put("description", description);
jsonObject.put("weight", wt);
jsonObject.put("rate", rateAmt);
jsonObject.put("makingAmt", making);
jsonObject.put("net_rate", netr);
jsonObject.put("itemTotal", iTotal);
jsonObject.put("vat", vatAmt);
jsonObject.put("sum_total", sumAmt);
jsonObject.put("bill_type", billType);
jsonObject.put("date", crtDate);
} catch (JSONException e) {
e.printStackTrace();
}
try {
itemSelectedJson.put(index, jsonObject);
index++;
} catch (JSONException e) {
e.printStackTrace();
}
}
And this is the code that I use to update my json array which contains a json object.
try {
itemSelectedJson.getJSONObject(i).put("net_rate",netChange);
Log.d("NETRATE_TW",itemSelectedJson.toString());
} catch (JSONException e) {
e.printStackTrace();
}
Now the problem with this code is it updates the jsonArray everytime a new item is added to the code.So the first object values are the same as the last object.
Also note that I am using this code inside a text watcher.So the afterTextchanged() method looks like this.
#Override
public void afterTextChanged(Editable s) {
String netChange = netRate.getText().toString();
final int row_id = (int) newRow.getTag();
if ((row_id<0) || (row_id> itemSelectedJson.length())){
return;
}
try {
itemSelectedJson.getJSONObject(row_id-1).put("net_rate",netChange);
Log.d("NETRATE_TW",itemSelectedJson.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
};
This is the snapshot of what my database looks like.
A jSONObject(which is a collection of name,value pairs) can be converted into a JSONArray which is an ordered array of the "values" in the JSONObject.
This can be done using the .toJSONArray() method.
When you need to replace/update the JSONArray, you may use the method
.put(int index, java.util.Map value)
Unlike how you are doing at present, i.e getting the object and setting a new key and value.
http://www.json.org/javadoc/org/json/JSONArray.html#put(int, java.util.Map)
As I understood, your problem is in creating multiple JSONObjects in your JSONArray with the same values, and that's because you can't get the index of a created JSONObject inside your JSONArray, and to overcome this problem, you can easily create a compound JSONObject that contains your JSONObjects instead of a JSONArray contains JSONObjects, and the object name will be anything unique in your JSONObject data, and when you make any changes or add any item it will either be added as a new object if it doesn't exist or it will overwrite the existing object if it added before, for example let's suppose that barcode value is unique in your data, so the code will be like the following:
// declaring itemSelectedJson as JSONObject
JSONObject itemSelectedJson = new JSONObject();
.
.
.
// when wanting to add a new item
itemSelectedJson.put(jsonObject.getString("barcode"), jsonObject);
and to retrieve the data you simple iterate through this JSONObject:
Iterator<?> keys = itemSelectedJson.keys();
JSONObject single_item;
while(keys.hasNext()) {
String key = (String)keys.next();
single_item = itemSelectedJson.getJSONObject(key);
// do what do you want here
}
It is a question that has been asked many times but i didn't find any solution from the answers that they gave.
Basically im using the GSON to create instances of classes to JSON in order to serialize them and store it into the cloud save.
Here is the code
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
User user = dbmanager.getUser();
String user_json = gson.toJson(user);
saved_data.put("user", user_json);
The dbmanager.getUser(); is an Sql query that collects the user from the android database and return it as an instance of the User class.
Then i'm using the load method to load the data
public void converLoadData(String data) throws ParseException
{
if (data == null || data.trim().equals("")) return;
try {
User user = new User();
data = data.replace("\\\\", "\\");
JSONObject obj = new JSONObject(data);
System.out.println("data: " + obj.toString());
JSONObject user_object = obj.getJSONObject("user");
System.out.println("user " + user_object.toString());
String last_sync = obj.getString("last_sync");
java.util.Date db_sync = dbmanager.getLastSync(user.getID());
}
catch (JSONException ex) {
ex.printStackTrace();
Log.e(TAG, "Save data has a syntax error: " + data, ex);
}
catch (NumberFormatException ex) {
ex.printStackTrace();
throw new RuntimeException("Save data has an invalid number in it: " + data, ex);
}
}
The return of the println of data is this one
data: {"current":"{\"title\":\"Puzzle
2\",\"fnMoves\":[],\"solution_path\":\"puzzles\/2\/CKqbKz5f\/7b1886a261b0400768e75dea91948576.json\",\"puzzlecolors\":[0,0,0],\"puzzle_path\":\"puzzles\/2\/CKqbKz5f\/41a0b30fdfdf6685dd50c6019391cc00.tmx\",\"level_id\":2,\"locked\":false,\"level\":2,\"puzzle_site_id\":2,\"id\":2,\"score\":20,\"fnkeys\":1,\"solved\":false,\"difficulty\":1.0}","solved":"[{\"id\":1,\"puzzle_id\":1,\"puzzle_tries\":10,\"user_id\":1}]","user":"{\"personphoto\":\"https:\/\/lh4.googleusercontent.com\/-5XfDNwK1PwI\/AAAAAAAAAAI\/AAAAAAAAPs8\/C0onA9lyKvY\/photo.jpg?sz=50\",\"google_id\":\"fdgsdfgfgfgsdgsdf\",\"personname\":\"Test
Test\",\"last_sync\":\"2014-08-18
22:12:12\",\"lifes\":3,\"highscore\":13,\"ID\":1}","last_sync":"2014-08-18
22:12:12"}
and here is the error. This error has to do with the data value because i have back slash? i'm passing the data (which is string) into a JSON object and then i'm trying to collect the user element. using this JSONObject user_object = obj.getJSONObject("user"); and this is where i\m having the error. Anyone who can help me please? thank you
org.json.JSONException: Value {"personphoto":"https://lh4.googleusercontent.com/-5XfDNwK1PwI/AAAAAAAAAAI/AAAAAAAAPs8/C0onA9lyKvY/photo.jpg?sz=50","google_id":"104757400111626678244","personname":"George Panayi","last_sync":"2014-08-18 22:12:12","lifes":3,"highscore":13,"ID":1} at user of type java.lang.String cannot be converted to JSONObject
Solution: I'm using "remove" method to remove extra backslashes and quotes which cause bad format of the JSON Object
data = data.replace("\\", "");
data = data.replace("\"{", "{");
data = data.replace("}\"", "}");
data = data.replace("\"[", "[");
data = data.replace("]\"", "]");
I was able to get it working by cleaning up the JSON object a bit. I think it's just a bad formatting error.
First, the escape slashes, they need to be uniform or removed. I removed the ones escaping the double quotes, but left them in everywhere else.
Then I removed the double quotes around the nested objects and arrays. "{...}" to {...} and "[...]" to [...]
Seems to be all that was necessary.
{"current":{"puzzle_path":"puzzles\/2\/CKqbKz5f\/41a0b30fdfdf6685dd50c6019391cc00.tmx","solved":false,"score":20,"difficulty":1,"level_id":2,"id":2,"fnkeys":1,"title":"Puzzle\n2","level":2,"solution_path":"puzzles\/2\/CKqbKz5f\/7b1886a261b0400768e75dea91948576.json","puzzlecolors":[0,0,0],"puzzle_site_id":2,"locked":false,"fnMoves":[]},"user":{"ID":1,"lifes":3,"google_id":"fdgsdfgfgfgsdgsdf","highscore":13,"last_sync":"2014-08-18\n22:12:12","personname":"Test\nTest","personphoto":"https:\/\/lh4.googleusercontent.com\/-5XfDNwK1PwI\/AAAAAAAAAAI\/AAAAAAAAPs8\/C0onA9lyKvY\/photo.jpg?sz=50"},"solved":[{"puzzle_id":1,"id":1,"user_id":1,"puzzle_tries":10}],"last_sync":"2014-08-18\n22:12:12"}
Hey guys I was looking through parse.com examples and documentation but haven't been able to figure out how to change the value of something that's stored in a column in a parse class(specifically a string that's a number e.g., Column name:ExampleColumn - string - 5) . For example I want to do something like this when a button is clicked
#Override
public void onClick(View arg0) {
ParseQuery<ParseObject> query = new ParseQuery<ParseObject> ("ExampleClass");
ExampleColumn = ExampleColumn + 1; /* obviously this won't work but it shows exactly what i want to do with the column, so that this would make ExampleColumn = 6 */
}
With Parse, you don't work directly with columns. You work with objects. So, if you want to change the value of "a column", you need to
fetch the object (row) you want to change
edit the property on that object
save the object again.
If the column data type is string you have to convert to integer before increment it.
ParseQuery query = new ParseQuery ("ExampleClass");
query.whereEqualTo("objectId",your_object_id);
query.getFirstInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (object == null) {
Log.d("score", "The getFirst request failed.");
} else {
int val=Integer.parseInt(object.getString("exampleColumn"));
val++;
object.put("exampleColumn",val);
object.saveInBackground();
}
}
});