Reputation: 81
I'm trying to use an API that returns JSON, and I'm using Retrofit to get the response and parse it
the API retruns JSON like the following :
{
"total": 1244881,
"totalHits": 500,
"hits": [
{
"id": 5205518,
"pageURL": "https://pixabay.com/photos/landscape-sea-sky-clouds-sunset-5205518/",
"type": "photo",
"tags": "landscape, sea, sky",
"previewURL": "https://cdn.pixabay.com/photo/2020/05/22/14/04/landscape-5205518_150.jpg",
"webformatWidth": 640,
"webformatHeight": 427,
...
...
},
...
...
]
}
And for The GSON to convert this json into an Object I created two classes :
the first is : RquestModel.java
public class RequestModel {
@SerializedName("total")
private long total;
@SerializedName("totalHits")
private long totalHits;
@SerializedName("hits")
private List<Image> hits;
//Getters and setters down here...
}
and the second class for the array in the json is :
public class Image {
@SerializedName("id")
private long id;
@SerializedName("pageURL")
private String pageURL;
@SerializedName("type")
private String type;
@SerializedName("tags")
private String tags;
@SerializedName("previewURL")
private String previewURL;
@SerializedName("previewWidth")
private long previewWidth;
@SerializedName("previewHeight")
private long previewHeight;
@SerializedName("webformatURL")
private String webformatURL;
@SerializedName("webformatWidth")
private long webformatWidth;
@SerializedName("webformatHeight")
private long webformatHeight;
@SerializedName("largeImageURL")
private String largeImageURL;
@SerializedName("imageWidth")
private long imageWidth;
@SerializedName("imageHeight")
private long imageHeight;
@SerializedName("imageSize")
private long imageSize;
@SerializedName("views")
private long views;
@SerializedName("downloads")
private long downloads;
@SerializedName("favorites")
private long favorites;
@SerializedName("likes")
private long likes;
@SerializedName("comments")
private long comments;
@SerializedName("user_id")
private long userId;
@SerializedName("user")
private String user;
@SerializedName("userImageURL")
private String userImageURL;
//Getters and Setters down here .....
}
And for the interface that the GSON converter uses is like this :
public interface ImageAPIService {
@GET(".")
public Call<RequestModel> getRequest();
}
and When I try to use the response from the Callback like this :
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
ImageAPIService api = retrofit.create(ImageAPIService.class);
Call<RequestModel> request = api.getRequest();
request.enqueue(new Callback<RequestModel>() {
@Override
public void onResponse(Call<RequestModel> call, Response<RequestModel> response) {
mViewModel.setTxt(response.body().getTotal() + "");
}
@Override
public void onFailure(Call<RequestModel> call, Throwable t) {
}
});
that gives an Exception of type: java.lang.NullPointerException
:
java.lang.NullPointerException: Attempt to invoke virtual method 'long com.mapps.pixabayclient.models.RequestModel.getTotal()' on a null object reference
I tried to debug it and everything seems fine to me, I don't know what I have missed. if someone could notice the mistake, I'd be very thankful.
And thanks for your help in advance.
Upvotes: 1
Views: 679
Reputation: 3021
So, the problem as you already figured out is that with your setup, the key is getting removed from the request. This is the response when I make the request with your setup.
Response{protocol=http/1.1, code=400, message=Bad Request, url=https://pixabay.com/api/}
But it shouldn't be the case. According to this from Jake Wharton, if we use @GET(".")
, then the whole base_url becomes the request url. For some reason, that isn't the case for you. [Maybe if we log the request url using some interceptor then we can understand better what's going on (whether it's a retrofit issue or a backend issue)].
Anyways, one solution is to pass the api key for each request like the following:
@GET(".")
public Call<RequestModel> getRequest(@Query("key") String key);
and call the function like this:
api.getRequest("my_api_key")
Another solution is to hard-code the api key into @GET("api/?key=xxxxx")
like you already did.
The better solution is to use okhttp interceptor to intercept the requests and add the api key query parameter in the url. With this solution, you won't have to pass the api key for each function call.
Upvotes: 1
Reputation: 81
The problem was in the @GET
annotation, as I moved the api/?key inside the parenthesis of the GET annotation -> @GET("api/?key=xxxxxxx")
but the problem now is that I should pass the key in every GET or any other request type.
is there a workaround to systematically pass the key in each request ?
Upvotes: 0