JSON Object to generic ParseFile Object, issue - java

I have run in to an issue, while converting my iOS app to android.
The database is structured such that there are "stations", these stations can have multiple images attached, in the parse database, the images are an array of imagePointers.
When i wanted to get the images out in iOS here is what i did:
stations = object in this case
// Get a single image
if ([[object objectForKey:#"imagePointers"] objectAtIndex:0] != [NSNull null]) {
PFFile *imageFile = [[[object objectForKey:#"imagePointers"] objectAtIndex:0] objectForKey:#"image"];
cell.coverImageView.file = imageFile;
[cell.coverImageView loadInBackground];
}
Its pretty simple, i just lift the imagePointers array and get objectAtIndex0, then i cast it to a parse file.
But i can't do this in android, here is what i have atm:
JSONArray imagePointers = thisStation.getJSONArray("imagePointers");
try {
JSONObject indexImage = imagePointers.getJSONObject(0);
} catch ( Exception e ) {
JSONObject indexImage = null;
}
Here i get the object at index 0 as a JSONObject, i cannot use this in a ParseFile Object, since i need to cast it as a generic type ParseFile.
How do i do this? Or is my approach completely incorrect?

Fixed it by avoiding casting to JSON, apparently there is a getList method
// Get parse Image as index image
ParseObject thisStation = stationItems.get(position);
List<ParseObject>imagePointers = thisStation.getList("imagePointers");
ParseFile image = imagePointers.get(0).getParseFile("image");
thumbnail.setParseFile(image);
thumbnail.loadInBackground();

I had the same issue for almost 2 days but finally I solved it by the getList method!
Now all you gotta do is use getList instead of getJSONObject or getJSONArray or whatever, because when you use them you will not be able to use the getParseFile for any of those believe me.
But instead you can do something like:
val obj = parseObject.getList("listname")
val file = obj[0].getParseFile("image")
Now, I don't remember how the syntex is or so but the key here is to use the getList method if you want to get list of all images you saved in a Back4app Parse JSONArray.
Hope you found it helpful.
Goodluck

Related

How to rename the key of a JSON Response dynamically in Retrofit2 Android

I have a JSON response like this:
{
"AED_BDT": 23.100486
}
But the key changes according to my query like if my query is USD_BDT, then it will give response like this:
{
"USD_BDT": 23.100486
}
So,that means I need to change the JSON key according to my query. But I couldn't find any solution on how to do this.
I tried by converting the response body into String and then replaced the Key according to my query, but this is not working..
This is my model class:
data class ResponseCurrencyConvert(
val USD_BDT: Double
)
This is what I tried so far:
val params = HashMap<String,String>()
params["compact"]="ultra"
params["apiKey"]= API_KEY
params["q"]="${currencyFrom}_${currencyTo}"//getting specific currencies and then setting them as query,i.e:USD_BDT
message(TAG,"Query: ${params["q"]}")
prefManager.query=params["q"]!!
//calling the API
apiServices.convertCurrency(params).enqueue(object : Callback<ResponseCurrencyConvert>{
override fun onFailure(call: Call<ResponseCurrencyConvert>, t: Throwable) {
message(TAG,"onFailure: ${t.localizedMessage}")
}
override fun onResponse(call: Call<ResponseCurrencyConvert>, response: Response<ResponseCurrencyConvert>) {
message(TAG,"onResponse Code: ${response.code()}")
message(TAG,"onResponse Body: ${Gson().toJson(response.body())}")
val json = Gson().toJson(response.body())//converting the response as string
val oldValue = "USD_BDT"//the key which was in my model class
val newValue=params["q"]// the new key which is my query
val output = json.replace(oldValue,newValue!!,false) // replacing the default query with my query
val newResponse = Gson().fromJson(output,ResponseCurrencyConvert::class.java)//again converting the new replaced string to json
if (response.isSuccessful){
message(TAG,"Output: $output")
message(TAG,"onResponse Result: ${newResponse?.USD_BDT}")
message(TAG,"onResponse newResult: ${newResponse.USD_BDT}")
rate= newResponse?.USD_BDT//getting the value; this is returning 0 every time expect when my query is USD_BDT
I commented everything that I did on the code, please read that carefully. Your help is highly appreciated..
Keys are defined from the server only I guess
The best way you can do is like keep both keys and make it nullable
else you have an alternate name in JSON parsing
A way to do that is maintaining the 2 different keys, which is the most simple and effective.
Another way to accomplish this is changing the Response type to string. When you get the response you change the JSON string, changing the key name and then use GSON to manually convert from JSON to Object.
Maybe it can be done also with a Custom Json Converter, but I don't think is worth.
If the key changes for every other response, I would suggest using HashMap<String, String>. Instead of mapping directly to String value which changes dynamically using HashMap would solve your issue.
Let me know how it goes.

Parse List<Object> on java beanutils.populate

I'm new at java beanutils and i'm getting a really hard time to figure out how can i accomplish this.
I can get all fields from Html FORM, an populate with beanutils.populate(Object, request.getParamterMap());
All works, even fields mapped as "CustomClass someobj", i had a little trouble but with form input field nominate as "someobj.field" i can get its right.
Now i need to do a map as List listobj but i dont know how.
Tried in form name as "listobj[].field", "listobj.[].field", "listobj.[]field", "listobj[][field]", but none of this work. I can do it manually via setProperty("listobj",List<CustomClass>);
I got it.
For anyone with the same problem, what i did was:
In Html form
name="indexedListobj[listobj.id].field"
I'm using hibernate so my object are now Set<CustomClass> listobj instead of List<CustomClass> listobj to prevent collection exception.
What i did was to create another method for check an index against objects in Set, then, update object if exists, or append a new if not. like this:
public CustomClass getindexedListobj(int index) {
CustomClass tmp = null;
for(CustomClass o : this.listobj)
if(o.getId() == index) {
tmp = o;
break;
}
if(tmp == null) {
tmp = new CustomClass();
this.listobj.add(tmp);
}
return tmp;
}

Processing: how to check if JSON Objects are bound

Since the Processing forum is down I hope one of you guys can help me out.
I made a Processing sketch that pulls data from an API (test here: http://www.europeana.eu/portal/api/console.html ) in JSON-format and reads some fields of this data for visualization. Everything works fine so far except when there are fields that are not bound to every JSONObject.
This is the code for the retrieval of the data:
JSONObject json;
json = loadJSONObject("data.json"); // loading my JSON file into the object
JSONArray CHOData = json.getJSONArray("items"); // array of the items I want data from
for (int i = 0; i < CHOData.size(); i++) {
JSONObject CHO = CHOData.getJSONObject(i); // get a specific item
JSONArray previewObj = CHO.getJSONArray("edmPreview"); // this field is an array, so I need to store it in a JSONArray object first
String[] previewArray = previewObj.getStringArray(); // here I store it in my actual string array
String preview = previewArray[0]; // I only need the first element
}
As you can see, I want the first string of the "edmPreview" array in the object. When I run the sketch, I get an error: "JSONObject["edmPreview"] not found."
This is of course because not every item has such an object. But how can I test if there is an object with this name in an item? I tried with if(CHO.getJSONObject("edmPreview") != null), but same error. Is there a way to look into the JSONObject and check the data values for something called "edmPreview"? There is no such function explained in the Processing reference.
The JSON file essentially looks as follows:
{
"items": [
{
"id": "someID",
"edmPreview": [
"http://europeanastatic.eu/api/image?uri=someimage.jpg"
],
// some other fields
}, // some other items
]
}
I'm new to this JSON-stuff, so maybe I miss something important... Thanks for the help!
So I found the answer myself, but not in the Processing reference, but in the actual reference for the JSONObject class in Java (http://www.json.org/javadoc/org/json/JSONObject.html). I tried some of the methods there and found that hasKey() (which is actually something I came up with myself, combining the method "has()" with the term "key", pure coincidence) as a boolean value works very well:
String preview = "";
if (CHO.hasKey("edmPreview")) {
JSONArray previewObj = CHO.getJSONArray("edmPreview");
String[] previewArray = previewObj.getStringArray();
preview = previewArray[0];
}
So now I learned that Processing is essentially just Java and sometimes not every method is written in the Reference. :-)

Why does JSONTokener/Object keep randomizing my json data?

I've been trying to debug this problem for hours and have Googled it and can't even find someone who's having the same problem. For some reason JSONObject/JSONTokener is doing bizarre things.
The following code:
JSONObject jsonObj = (JSONObject) new JSONTokener(sourceJson).nextValue();
Log.d(" ", sourceJson + "\n");
Log.d(" ", jsonObj.toString());
Produces this output:
{
"2012":{
"federal":[[10822,0.15],[42707,0.22],[85414,0.26],[132406,0.29]],
"provincial":{
"AB":[[17282,0.1]],
"BC":[[11354,0.0506],[37013,0.077],[74028,0.105],[84993,0.1229],[103205,0.147]],
"MB":[[8634,0.108],[31000,0.1275],[67000,0.174]],
"NB":[[9203,0.091],[38190,0.121],[76380,0.124],[124178,0.143]],
"NL":[[8237,0.077],[32893,0.125],[65785,0.133]],
"NS":[[8481,0.0879],[29590,0.1495],[59180,0.1667],[93000,0.175],[150000,0.21]],
"NT":[[13280,0.059],[38679,0.086],[77360,0.122],[125771,0.1405]],
"NU":[[12211,0.04],[40721,0.07],[81442,0.09],[132406,0.115]],
"ON":[[9405,0.0505],[39020,0.0915],[78043,0.1116],[500000,0.1216]],
"PE":[[7708,0.098],[31984,0.138],[63969,0.167]],
"QC":[[10925,0.16],[40100,0.2],[80200,0.24]],
"SK":[[14942,0.11],[42065,0.13],[120185,0.15]],
"YT":[[10822,0.0704],[42707,0.0968],[85414,0.1144],[132406,0.1276]]
}
}
}
{"2012":{"provincial":{"ON":[[9405,0.0505],[39020,0.0915],[78043,0.1116],[500000,0.1216]],"AB":[[17282,0.1]],"BC":[[11354,0.0506],[37013,0.077],[74028,0.105],[84993,0.1229],[103205,0.147]],"NL":[[8237,0.077],[32893,0.125],[65785,0.133]],"QC":[[10925,0.16],[40100,0.2],[80200,0.24]],"NU":[[12211,0.04],[40721,0.07],[81442,0.09],[132406,0.115]],"SK":[[14942,0.11],[42065,0.13],[120185,0.15]],"PE":[[7708,0.098],[31984,0.138],[63969,0.167]],"NT":[[13280,0.059],[38679,0.086],[77360,0.122],[125771,0.1405]],"NS":[[8481,0.0879],[29590,0.1495],[59180,0.1667],[93000,0.175],[150000,0.21]],"YT":[[10822,0.0704],[42707,0.0968],[85414,0.1144],[132406,0.1276]],"NB":[[9203,0.091],[38190,0.121],[76380,0.124],[124178,0.143]],"MB":[[8634,0.108],[31000,0.1275],[67000,0.174]]},"federal":[[10822,0.15],[42707,0.22],[85414,0.26],[132406,0.29]]}}
The nicely formatted data above is identical to the data.json file that I used to populate sourceJson and the very long line has had the order of the provinces mysteriously rearranged (but not the data within each province's 2D array).
I've also tried:
JSONObject jsonObj = new JSONObject(sourceJson); // same problem
and
JSONTokener jsonTk = new JSONTokener(sourceJson);
Log.d(" ", jsonTk.toString()); // result = " at character 0 of " + sourceJson;
Log.d(" ", jsonTk.nextValue().toString()); // output same as original problem
I also tried to using a breakpoint to trace the call to nextValue() but couldn't find the cause of the problem. The behavior suggests that the JSONObject(String) constructor may call nextValue(), since both methods give the same output.
So the question is: Does anyone know why JSONObject/JSONTokener.nextValue() behaves this way? And, more importantly, do you know how to get it to parse the JSON data without reorganizing it? (I need to iterate through the data, even if the data file changes in the future)
Thanks a bunch!
JSON objects (nodes) are not ordered. It is definition of json format. In Java are JSON nodes implemented as HashMap and HashMap is not ordered too.
If you really need something ordered in JSON, you need to use JSON Array. Example:
{
"2012":{
"federal":[[10822,0.15],[42707,0.22],[85414,0.26],[132406,0.29]],
"provincial":{
["code":"AB", data:[[17282,0.1]]],
["code":"BC", data:[[11354,0.0506],[37013,0.077],[74028,0.105],[84993,0.1229],[103205,0.147]]],
["code":"MB", data:[[8634,0.108],[31000,0.1275],[67000,0.174]]]
.
.
.

Java JSONArray from Javascript JSONArray

I am passing a json object from javascript to a java servlet using ajax.
var jsonObj = JSON.stringify(objArray); //Then I pass it to Java using ajax.
In my Java I am getting the json string from the request, then creating a jsonarray, then looping through that array and i'm getting errors when trying to pull one of the json objects from the array.
String dataObj = request.getParameter("obj");
String sql = request.getParameter("sql");
ArrayList<Object> returnArray = new ArrayList<Object>();
int key;
//Get type of object being passed.
JSONArray jsonArray = JSONArray.fromObject(dataObj);
for(int i=0; i<jsonArray.size(); i++) {
String obj = new Gson().toJson(jsonArray.getJSONObject(i)); //This is where i'm getting an error
String className = getClassName(jsonArray.getJSONObject(i));
Class targetClass = null;
try {
targetClass = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//Create Object
Object data = new Gson().fromJson(obj, targetClass);
I'm posting the relevant code, the for loop isn't closed because the rest of the code is quite long, and this is the part where i'm getting the error.
net.sf.json.JSONException: JSONArray[0] is not a JSONObject.
Here is what the json array looks like when its passed in from javascript. This is a println of the jsonArray object.
[{"number":"(123) 456-7050","type":"Home","contactId":1,"id":16662,"className":"beans.PhoneNumber","position":0}]
With one object in it, this code works. But as soon as I get 2 or more, my error comes up.
[[{"number":"(123) 456-7050","type":"Home","contactId":1,"id":16662,"className":"beans.PhoneNumber","position":1},{"number":"(555) 555-1233","type":"Mobile","contactId":1,"id":16656,"className":"beans.PhoneNumber","position":0},{"number":"(999) 999-9999","type":"Home","contactId":1,"id":16664,"className":"beans.PhoneNumber","position":3},{"number":"(222) 222-2222","type":"Home","contactId":1,"id":16666,"className":"beans.PhoneNumber","position":4}]]
It almost looks like when i'm passing more than one object, it create an array of an array, which could be why its not working. But how do I avoid doing that when i'm passing a jsonarray from javascript? Using just the dataObj I have no access to size or get to loop through it.
[
[
{
"number":"(123) 456-7050","type":"Home",
"contactId":1,
"id":16662,
"className":"beans.PhoneNumber",
"position":1
},
{
"number":"(555) 555-1233",
"type":"Mobile",
"contactId":1,
"id":16656,
"className":"beans.PhoneNumber",
"position":0
},
{
"number":"(999) 999-9999",
"type":"Home",
"contactId":1,
"id":16664,
"className":"beans.PhoneNumber",
"position":3
},
{
"number":"(222) 222-2222",
"type":"Home",
"contactId":1,
"id":16666,
"className":"beans.PhoneNumber",
"position":4
}
]
]
This is not an array of objects. This is an array of arrays of objects. According to your description, you are expecting something like the following to be fed to your Java:
[{"foo":"bar"}, {"bar":"baz"}]
But you are really trying to parse:
[[{"foo":"bar"}, {"bar":"baz"}]]
I am not completely sure, because you have not shared the json that you are trying to parse, but the most probable error you have is just what it says: the first element of the array is not JSONObject. Note that string values, lons and booleans are not JSONObjects. I would suggest you to use the more genereal JSONArray.get and check instance of what class it is. Maybe this can head you to the problem with the json you have. If I got it completely wrong - write back and I will try to help. In such a case it will be still useful to share the results of the proposed experiment.
EDIT:
This is double array -> maybe you using getJSONArray(int index) will help you. as the other answer mentioned - this is array of arrays. Also consider changing the javascript to reduce the level of arrays included.

Categories