json array value from volley into hashmap string, string - java

i have a request to build slider image from jsonArray using volley, i don't know how to put value of jsonArray to hashmap<string, string> .. it keep saying null object
error message
Attempt to invoke virtual method 'java.lang.Object
java.util.HashMap.put(java.lang.Object, java.lang.Object)' on a null object reference
JSON array value
[
{"cPID":"62001002280293829",
"image":"http:\/\/ibigcreative.com\/dev\/assets\/images\/slider\/rsch.jpg"},
{"cPID":"62001002020254584",
"image":"http:\/\/ibigcreative.com\/dev\/assets\/images\/slider\/penang.jpg"},
{"cPID":"62001002050264258",
"image":"http:\/\/ibigcreative.com\/dev\/assets\/images\/slider\/guardian.jpg"}
]
and then i wanna put that value like this into hashmap<string, string> inside onCreate()
HashMap<String,String> url_maps = new HashMap<>();
url_maps.put("Hannibal", "http://static2.hypable.com/wp-content/uploads/2013/12/hannibal-season-2-release-date.jpg");
url_maps.put("Big Bang Theory", "http://tvfiles.alphacoders.com/100/hdclearart-10.png");
url_maps.put("House of Cards", "http://cdn3.nflximg.net/images/3093/2043093.jpg");
url_maps.put("Game of Thrones", "http://images.boomsbeat.com/data/images/full/19640/game-of-thrones-season-4-jpg.jpg");
it gonna use for adding picture to my slider(slideshow) inside onCreate()
for(String name : url_maps.keySet()){
DefaultSliderView DefaultSliderView = new DefaultSliderView(getContext());
// initialize a SliderLayout
DefaultSliderView
.image(url_maps.get(name))
.setScaleType(BaseSliderView.ScaleType.Fit)
.setOnSliderClickListener(this);
//add your extra information
DefaultSliderView.bundle(new Bundle());
DefaultSliderView.getBundle()
.putString("extra",name);
mDemoSlider.addSlider(DefaultSliderView);
}
and i don't know how to put values from volley JsonArray, and this is my request but error saying null.
private void getSlider(){
String tag_string_req = "sliderList";
// Showing progress dialog before making http request
JsonArrayRequest mostReq = new JsonArrayRequest(AppConfig.URL_Slider, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
try {
for (int i = 0; i < 5; i++) {
JSONObject jObj = response.getJSONObject(i);
url_maps.put(jObj.getString("cPID"), jObj.getString("image"));
}
}
catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + "Error Data Occured!!" + error.getMessage());
Toast.makeText(getContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
hideDialog();
}
}) ;
AppController.getInstance().addToRequestQueue(mostReq, tag_string_req);
}
the values request was accepted on volley, it show on Logcat .. but null on hashmap .. tell me if i got mistake in my code, sorry just newbie and still study

You are iterating thru just the keys... You need to iterate through the keys and values...
for (url_maps.Entry<String, String> url_map : url_maps.entrySet()) {
String key = url_map.getKey();
String value = url_map.getValue();
// ...
}
ANOTHER WAY TO ATTEMPT THIS IS...
to deserialize your Json into a java object...
ObjectMapper mapper = new ObjectMapper();
string StringJson = "[
{"cPID":"62001002280293829",
"image":"http:\/\/ibigcreative.com\/dev\/assets\/images\/slider\/rsch.jpg"},
{"cPID":"62001002020254584",
"image":"http:\/\/ibigcreative.com\/dev\/assets\/images\/slider\/penang.jpg"},
{"cPID":"62001002050264258",
"image":"http:\/\/ibigcreative.com\/dev\/assets\/images\/slider\/guardian.jpg"}
]";
// For the following line to work you will need to make a URLMaps Class to hold the objects
URLMaps urlMaps = mapper.readValue(StringJson , URLMaps.class);
The URLMaps Class might look like this.
public class URLMaps{
public string name = "";
public string image = "";
//constructor
public URLMaps(string a, string b) {
name = a;
image = b;
}
public string getName() {
return name;
}
public string getImage() {
return image;
}
}
Then to utilize the class you can go with:
urlMaps.getName(), or urlMaps.getValue() in your DefaultSliderView.image()
Also to note, since this is a class you can store an array of them or a list of them, so you can re-purpose your for loop...
For (URLMap urlmap : UrlMaps[]) // where URLMaps is your object that holds multiple instances of URLMaps.
Lastly, it has been a long time since I have coded in Java, so this code is untested, but should help you come to a solution.

Related

How to add results of Facebook Graph api to array list in Java

I am using the Facebook graph api to find out what pages a user is apart of. When the query comes back with a json object it has what I need but, for some reason it doesn't want to add to my array list. The correct value is printed in log.d it seems to skip my arraylist for some reason. Any ideas?
Find page function
private ArrayList<String> foundPages;
private JSONObject jsonObject;
public ArrayList<String> findPages()
{
accessToken = AccessToken.getCurrentAccessToken();
foundPages = new ArrayList<>();
GraphRequest request = GraphRequest.newGraphPathRequest(
accessToken,
"/me/accounts",
new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse response) {
try {
jsonObject = response.getJSONObject();
for(int i=0; i < jsonObject.getJSONArray("data").length(); i++)
{
page = response.getJSONObject().getJSONArray("data").getJSONObject(i).getString("name");
Log.d("viewmodel",page);
foundPages.add(page);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
request.executeAsync();
return foundPages;
}
There is a common way to solve this problem, which is to define a callback method which will return these values to you, AFTER they have been populated by the call, which goes something like this (my java is rusty, bear with me...)
define an interface :
interface Callback{
void apiResponseCallback(ArrayList<Page> result);//whatever your model is, make the array of that type
}
then, in your normal findPages method, change it to this:
public void findPages(Callback callback) {
//
//
........
for(int i=0; i < jsonObject.getJSONArray("data").length(); i++)
{
page = response.getJSONObject().getJSONArray("data").getJSONObject(i).getString("name");
Log.d("viewmodel",page);
foundPages.add(page);
}
callback.apiResponseCallback(foundPages);//here we are returning the data when it is done
}
then, when you call findPages
findPages(new Callback() {
#Override
public void apiResponseCallback(ArrayList<Page> result) {
here, this result parameter that comes through is your api call result to use, so result will be your populated pages to use.
}
});
}
sake of completeness:
public void findPages(Callback callback)
{
accessToken = AccessToken.getCurrentAccessToken();
foundPages = new ArrayList<>();
GraphRequest request = GraphRequest.newGraphPathRequest(
accessToken,
"/me/accounts",
new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse response) {
try {
jsonObject = response.getJSONObject();
for(int i=0; i < jsonObject.getJSONArray("data").length(); i++)
{
page = response.getJSONObject().getJSONArray("data").getJSONObject(i).getString("name");
Log.d("viewmodel",page);
foundPages.add(page);
}
callback.apiResponseCallback(foundPages);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
request.executeAsync();
}
Yep. This here:
request.executeAsync();
triggers an asynchronous request. But your "current" thread simply continues to do:
return foundPages;
and it returns an empty list.
That list gets later filled, but at the moment in time when that method returns, that list is still empty. Or just gets filled. Who knows, as it gets filled asynchronously, at some unknown point in the future.
A solution could be to have some other variable/field that tells you the data has arrived and pushed into the list.
Alternatively, that method could just make a synchronous request, simply block the caller from progressing until the data has arrived.
You see, you can't have it both ways: when you don't wait for your results to arrive, you shouldn't expect them to be available immediately.

How to use ArrayAdapter and JSONArray for a listView

So far I can send a Get request to a server with a letter added to the url :
private void GetDevice() {
String deviceId = editTextDeviceId.getText().toString().trim();
if(TextUtils.isEmpty(deviceId)){
editTextDeviceId.setError("Please enter deviceId");
editTextDeviceId.requestFocus();
}
HashMap<String, String>params = new HashMap<>();
params.put("deviceID", deviceId);
PerformNetworkRequest request = new PerformNetworkRequest(Api.URL_GETBYDEVICEID + deviceId, null, CODE_GET_REQUEST);
request.execute();
}
When I press the button Search it sends the request :
buttonSearch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
GetDevice();
}
});
The server response is JSONArray :
W/System.err: org.json.JSONException: Value [{"DeviceId":"T","TransactionValue":2,"RSSI":2,"Time":"2018-08-02T14:43:00"}] of type org.json.JSONArray cannot be converted to JSONObject
Here is my problem.
From what I read, I know I need to use an ArrayList and ArrayAdapter to convert it into a JSONObject. Am I right so far ?
Here is where I’m stuck, as I don’t understand how to do it.
Many thanks in advance!
The JSON string returned from the server is a Json array,
so you need to convert it to a Jsonarray as follows, the jsonString here is the JSON string returned.
try {
JSONArray array=new JSONArray(jsonString);
} catch (JSONException e) {
e.printStackTrace();
}
The param you send is a JSONArray ,and the param that the server needs is a JSONObject.
The structure of JSONObject is like { },and a JSONArray is like [ { } , { } , ...... , { } ].So, you can change your param to {"DeviceId":"T","TransactionValue":2,"RSSI":2,"Time":"2018-08-02T14:43:00"} or edit the code of the server to receive parameters with JSONArray.
Try this:
You need to add array adapter
ArrayList<String> items = new ArrayList<String>();
for(int i=0; i < jArray.length() ; i++) {
json_data = jArray.getJSONObject(i);
String deviceID=json_data.getString("deviceID");
items.add(deviceID);
Log.d(deviceID,"Output"+deviceID);
}
ArrayAdapter<String> mArrayAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item, items));
setListAdapter(mArrayAdapter);
add device id in Hashmap it works

My Retrofit call.enque() method is getting skipped over entirely, not sure why

I'm making a call using Retrofit's enqueue() method. I'm calling my refreshImages() in my MainActivity's onCreate(), refreshImages() then calls a method refreshImagesIds() which is supposed to make a call out to Flickr's API and return back a PhotosList object, I'll then pull out the Photos from there which will contain a list of Photo objects. My issue is that for some reason the onResponse() inside my enqueue() method is never getting called. When I use the debugger it skips right over it, and when I put Log statements inside they never get written out. I know the endpoint it is hitting is correct because I can see it using OkHttp's logger, and my POJOs all look to be correct for the data being returned.
Any idea why this isn't working? Below are my refreshImages and refreshImagesId. These are both contained in my MainAcitivty and modify class-level variables.
private void refreshImages() {
// make api call
//imageUrls = FlickrServiceManager_withinterface.getKittenImages(8);
refreshImageIds();
List<Photo> photos = photosList.getPhotos().getPhoto();
imageIds = new ArrayList<String>();
for(Photo photo : photos) {
Log.d("TAG", "It is pringint imageIds: " + photo.getId());
imageIds.add(photo.getId());
}
}
private void refreshImageIds() {
Retrofit retrofit = Api.getRestAdapter();
FlickrServiceInterface flickrService = retrofit.create(FlickrServiceInterface.class);
Call<PhotosList> call = flickrService.getPhotos(API_KEY, FORMAT, "1");
imageIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
photosList = response.body();
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "Call failed");
}
});
}
And my FlickrServiceInterface:
public interface FlickrServiceInterface {
#GET("?method=flickr.photos.getSizes")
Call<PhotoSizes> getPhotoSizes(#Query("api_key") String apiKey, #Query("format") String format, #Query("nojsoncallback") String jsonCallback, #Query("photo_id") String photoId);
#GET("?method=flickr.photos.getRecent")
Call<PhotosList> getPhotos(#Query("api_key") String apiKey, #Query("format") String format, #Query("nojsoncallback") String jsonCallback);
}
Change your call to the synchronous retrofit API :
public static List<String> getImageIds(int size) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
photoIds = new ArrayList<String>();
PhotosList photosList = call.execute().body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
Please note that you need to call this method on an AsyncTask
EDIT
You could also continue to use enqueue, but you need to provide an "onFinish" hook, so you know when your data has been received and then you "notify" the client with the data:
//interface por communication
public interface ImageIdsCallBack {
public void onFinish( List<String> photoIds );
}
Then you receive this interface and send data:
public static List<String> getImageIds(int size, final ImageIdsCallBack callback) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
photoIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
PhotosList photosList = response.body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
//send the data to the caller
callback.onFinish(photoIds);
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "Call failed");
}
});
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
calling the method :
getImageIds( 50 , new ImageIdsCallBack() {
public void onFinish( List<String> photoIds ) {
//update UI with photoIds
}
} );
I typically use a library like EventBus to make it easier, I really recommend it to you.
Correct me if I'm wrong, is this on the main thread? That would pose the problem of not waiting for a response.
Consider using async

Convert string to json object gives an error

I have to send the json array to web server. I have created json array from array list. I have a helper class which sends json object to server.
So I want to convert the json array to json object.
I tried to do this:
Async Task:
public class SendMultipleInvitesAsyncTask extends AsyncTask<String, Void, JSONObject> {
private Context context;
JSONArray array = new JSONArray();
public SendMultipleInvitesAsyncTask(Context context)
{
this.context = context;
}
#Override
protected JSONObject doInBackground(String... params) {
try {
String api = context.getResources().getString(R.string.server_url) + "contactsapi/sendMultipleInvite.php";
JSONObject obj = new JSONObject(params[0]);
ServerRequest request = new ServerRequest(api,obj);
return request.sendRequest();
} catch(JSONException je) {
return Excpetion2JSON.getJSON(je);
}
}
Activity :
public class SendMultipleInvites extends AppCompatActivity {
private ArrayList<Invitation> invitationArrayList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_send_multiple_invites);
invitationArrayList = new ArrayList<>();
Invitation invitation = new Invitation("3","17/02/2016","55165122","1","user10");
invitationArrayList.add(invitation);
invitation = new Invitation("3","17/02/2016","282751221","1","user10");
invitationArrayList.add(invitation);
// JSONArray jsArray = new JSONArray(invitationArrayList);
Gson gson=new Gson();
String toServer=gson.toJson(invitationArrayList);
new SendMultipleInvitesAsyncTask(SendMultipleInvites.this).execute(toServer);
But this gives me an error that json object can not be converted to json array.
I want to send input of json array like this:
{
"invitations": [
{
"sender_id" : 3,
"date" : "12/08/2016",
"invitee_no" : "196756456",
"status" : "1",
"user_name" : "user10"
},
{
"sender_id" : 3,
"date" : "12/08/2016",
"invitee_no" : "13633469",
"status" : "1",
"user_name" : "user9"
}
]
}
How can I do this? How to pass it through an async task. Or what is going wrong here? Please help Thank you..
invitationArrayList is your ArrayList so jo get a JSON array. If you want to wrap this array in a JSON object you have to this in java as well.
For example:
String toServer = gson.toJson(
Collections.singletonMap("invitations", invitationArrayList)
);
(assumed that gson.toJson works as expected. I'm no gson expert because I'm mostly use jackson...)
JavaDoc for Collections.singletonMap: https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#singletonMap(K,%20V)

How do I get data from JSON string?

Here is my code:
try {
JSONObject json = (JSONObject) new JSONTokener(result).nextValue();
System.out.println(json);
JSONObject json2 = json.getJSONObject("data");
String test = json2.getString("headline");
System.out.println(test);
} catch (JSONException e) {
e.printStackTrace();
}
My String values start with the object data. So I am trying to get that object first and then capture the the object headline inside that.
My problem is, it is not taking the object data from the string.
Once I reach the line JSONObject json2 = json.getJSONObject("data");, it throws the exception. Please shed some light on this.
"data": [
{
"headline": "Close Update"
"docSource": "MIDNIGHTTRADER",
"source": "MTClosing",
"dateTime": "2015-10-23T16:42:46-05:00",
"link": "Markets/News",
"docKey": "1413-A1067083-1B14K77PVTUM1O7PCAFMI3SJO4",
},
The value for the key data is a JSON array containing one object, and not an object itself.
To get that object inside data, replace your line that throws an exception with the following:
JSONObject json2 = json.getJSONArray("data").get(0);
This gets the data array as a JSONArray object and then gets the 0th element, which is the object you want.
Your data "object", isn't actually an object, it's an array, notice the opening square bracket... I'm assuming in your actual code, it closes with one too.
"data": [{
"headline": "Close Update"
"docSource": "MIDNIGHTTRADER",
"source": "MTClosing",
"dateTime": "2015-10-23T16:42:46-05:00",
"link": "Markets/News",
"docKey": "1413-A1067083-1B14K77PVTUM1O7PCAFMI3SJO4",
}]
Try json.getJSONArray("data")[0] instead... or whatever index you need
try {
JSONObject json = (JSONObject) new JSONTokener(result).nextValue();
System.out.println(json);
JSONObject json2 = json.getJSONArray("data")[0];
String test = json2.getString("headline");
System.out.println(test);
}
catch (JSONException e) {
e.printStackTrace();
Your problem is based on the fact that your service returns and array instead of a single json object, so from here you can follow this suggestions to process directly from the JSONArray Can't access getJSONArray in java, or, at server side you can encapsulate your response array into another object like this (java example):
public class Data<T> {
private List<T> elements;
public ObjectSugetionsDTO(){
And build the response like this:
return new ResponseEntity<Data<YourInternalRepresentation>>(
new Data<YourInternalRepresentation>(yourMethodCallForTheArray()),
HttpStatus.OK);
I have found the second way to be better at keeping my API cleaner and more readable
EDIT: Better way
I whould also suggest the use of retrofit (http://square.github.io/retrofit/), by doing so, your service calls is resumed to (Example of calling and API that retrieves a list of users):
public class UserService {
public static IUserService getUserService() {
return RestAdapterManager.createService(IUserService.class );
}
public interface IUserService{
#GET("/api/users")
public void getAllUsers(Callback<List<User>> callback);
}
}
and the service call itself
UserService.getUserService().getAllUsers(new Callback<List<User>>() {
#Override
public void success(List<User> users, Response response) {
Log.d("Exito! " , "" + users.size());
}
#Override
public void failure(RetrofitError error) {
Log.d("Fail!", error.getUrl());
}
});
The simple inicialization of the connection object
public static <S> S createService(Class<S> serviceClass, String username, String password) {
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(API_BASE_URL);//Your api base url
RestAdapter adapter = builder.setLogLevel(RestAdapter.LogLevel.FULL).build(); //change the logging level if you need to, full is TOO verbose
return adapter.create(serviceClass);
}

Categories