Retrofit Returning Null Response Body
Based on my previous answer here your model is not correct your stat: "ok"
at the end of Response is your mistake.
While you create a Photos
Object you need a parent Model to keep both attribute (photos
& stat
)
So your model would be:
public class Model {
Photos photos;
int code;
String stat;
String message; // when you text = null
public class Photos{
int page;
int pages;
int perpage;
int total;
List<Photo> photo;
public class Photo{
String id;
String owner;
String secret;
//rest of things
}
}
}
Also don't forget to change your Call<Photos>
to Call<Model>
.
tccpg288
I quit my corporate job as a certified public accountant to learn computer programming. I am starting with Java / Android and eventually going to work to Shift / iOS. Currently, I have 2 applications published in the Google Play Store. I am maintaining these applications while finding ways to build new applications at the same time. Right now, I am starting to learn server-side programming, specifically Retrofit and Google App Engine Servlets. Let me know if you have any advice or can offer input!
Updated on August 02, 2022Comments
-
tccpg288 almost 2 years
I am trying to make a call to the FlickR API and am having difficulty as the response.body() is returning null.
I am not sure if it relates to my JSON/POJO mapping, but I cannot figure out how to access the response from Retrofit when I make the call to FlickR. I know that my call is being completed successfully as I am actually able to view the JSON through the logging interceptor.
Model:
public class Model { Photos photos; int code; String stat; String message; // when you text = null public class Photos { @SerializedName("page") @Expose private int page; @SerializedName("pages") @Expose private int pages; @SerializedName("perpage") @Expose private int perpage; @SerializedName("total") @Expose private String total; @SerializedName("photo") @Expose private List<Photo> photo = new ArrayList<Photo>(); /** * @return The page */ public int getPage() { return page; } /** * @param page The page */ public void setPage(int page) { this.page = page; } /** * @return The pages */ public int getPages() { return pages; } /** * @param pages The pages */ public void setPages(int pages) { this.pages = pages; } /** * @return The perpage */ public int getPerpage() { return perpage; } /** * @param perpage The perpage */ public void setPerpage(int perpage) { this.perpage = perpage; } /** * @return The total */ public String getTotal() { return total; } /** * @param total The total */ public void setTotal(String total) { this.total = total; } /** * @return The photo */ public List<Photo> getPhoto() { return photo; } /** * @param photo The photo */ public void setPhoto(List<Photo> photo) { this.photo = photo; } } public class Photo { @SerializedName("id") @Expose private String id; @SerializedName("owner") @Expose private String owner; @SerializedName("secret") @Expose private String secret; @SerializedName("server") @Expose private String server; @SerializedName("farm") @Expose private int farm; @SerializedName("title") @Expose private String title; @SerializedName("ispublic") @Expose private int ispublic; @SerializedName("isfriend") @Expose private int isfriend; @SerializedName("isfamily") @Expose private int isfamily; @SerializedName("url_m") @Expose private String urlM; @SerializedName("height_m") @Expose private String heightM; @SerializedName("width_m") @Expose private String widthM; public Photo(){ } /** * @return The id */ public String getId() { return id; } /** * @param id The id */ public void setId(String id) { this.id = id; } /** * @return The owner */ public String getOwner() { return owner; } /** * @param owner The owner */ public void setOwner(String owner) { this.owner = owner; } /** * @return The secret */ public String getSecret() { return secret; } /** * @param secret The secret */ public void setSecret(String secret) { this.secret = secret; } /** * @return The server */ public String getServer() { return server; } /** * @param server The server */ public void setServer(String server) { this.server = server; } /** * @return The farm */ public int getFarm() { return farm; } /** * @param farm The farm */ public void setFarm(int farm) { this.farm = farm; } /** * @return The title */ public String getTitle() { return title; } /** * @param title The title */ public void setTitle(String title) { this.title = title; } /** * @return The ispublic */ public int getIspublic() { return ispublic; } /** * @param ispublic The ispublic */ public void setIspublic(int ispublic) { this.ispublic = ispublic; } /** * @return The isfriend */ public int getIsfriend() { return isfriend; } /** * @param isfriend The isfriend */ public void setIsfriend(int isfriend) { this.isfriend = isfriend; } /** * @return The isfamily */ public int getIsfamily() { return isfamily; } /** * @param isfamily The isfamily */ public void setIsfamily(int isfamily) { this.isfamily = isfamily; } /** * @return The urlM */ public String getUrlM() { return urlM; } /** * @param urlM The url_m */ public void setUrlM(String urlM) { this.urlM = urlM; } /** * @return The heightM */ public String getHeightM() { return heightM; } /** * @param heightM The height_m */ public void setHeightM(String heightM) { this.heightM = heightM; } /** * @return The widthM */ public String getWidthM() { return widthM; } /** * @param widthM The width_m */ public void setWidthM(String widthM) { this.widthM = widthM; } } }
JSON Response:
{ photos: { page: 1, pages: 3683, perpage: 100, total: "368270", photo: [ { id: "29264707352", owner: "84316756@N02", secret: "9ed355a86e", server: "8603", farm: 9, title: "Tercer Patio de los Claustros de la Compañía/ Arequipa", ispublic: 1, isfriend: 0, isfamily: 0, url_m: "https://farm9.staticflickr.com/8603/29264707352_9ed355a86e.jpg", height_m: "500", width_m: "333" }, { id: "29339070436", owner: "146617764@N02", secret: "b52f1e9914", server: "8509", farm: 9, title: "2016-04-17 09.24.07", ispublic: 1, isfriend: 0, isfamily: 0, url_m: "https://farm9.staticflickr.com/8509/29339070436_b52f1e9914.jpg", height_m: "281", width_m: "500" },
LOGCAT
09-03 15:11:33.037 1846-1846/com.troychuinard.flickr_test E/AndroidRuntime: FATAL EXCEPTION: main Process: com.troychuinard.flickr_test, PID: 1846 java.lang.NullPointerException: println needs a message at android.util.Log.println_native(Native Method) at android.util.Log.v(Log.java:118) at com.troychuinard.flickr_test.MainActivity$1$1.onResponse(MainActivity.java:72) at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5254) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 09-03 15:14:21.858 1846-1846/com.troychuinard.flickr_test I/Process: Sending signal. PID: 1846 SIG: 9
Line 72
Log.v("RESPONSE_BODY", response.body().getTotal());
Activity
public class MainActivity extends AppCompatActivity { private EditText mSearchTerm; private Button mRequestButton; private Button mSearchButton; private String mQuery; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSearchTerm = (EditText) findViewById(R.id.ediText_search_term); mRequestButton = (Button) findViewById(R.id.request_button); mSearchButton = (Button) findViewById(R.id.search_button_flickr); mRequestButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mQuery = mSearchTerm.getText().toString(); HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.flickr.com/services/rest/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build(); ApiInterface apiInterface = retrofit.create(ApiInterface.class); Call<Photos> call = apiInterface.getImages(mQuery); call.enqueue(new Callback<Photos>() { @Override public void onResponse(Call<Photos> call, Response<Photos> response) { Log.v("RESPONSE_CALLED", "ON_RESPONSE_CALLED"); String didItWork = String.valueOf(response.isSuccessful()); Log.v("SUCCESS?", didItWork); Log.v("RESPONSE_CODE", String.valueOf(response.code())); Photos photos = response.body(); Log.v("RESPONSE_BODY", "response:" + photos); String total = response.body().getTotal(); Log.v("Total", total); List<Photos.Photo> photoResults = response.body().getPhoto(); for (Photos.Photo photo : photoResults) { Log.v("PHOTO_URL:", photo.getTitle() ); } } @Override public void onFailure(Call<Photos> call, Throwable t) { } }); } }); mSearchButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent toSearch = new Intent(MainActivity.this, FlickRActivity.class); startActivity(toSearch); } }); } //Synchronous vs. Asynchronous public interface ApiInterface { @GET("?method=flickr.photos.search&api_key=1c448390199c03a6f2d436c40defd90e&format=json&nojsoncallback=1&extras=url_m") Call<Photos> getImages(@Query("text") String query); }
}
-
tccpg288 over 7 yearsThanks I am trying to understand. I don't see how this model is different than my original code, and I don't understand what stat and message are for. Not saying you are wrong just trying to figure out where it comes into play
-
Amir over 7 years@tccpg288 I test your query with simple text; if you scroll to end of response a stat attribute exist; Also if you send null value to server it's return message and code.
-
Amir over 7 yearsYou get Null value because retrofit expect to see Object which contains photos and stat But saw photos and can't cast this object to each other :)
-
tccpg288 over 7 yearsHow do I scroll to the end of the response? I am having trouble even viewing the response...
-
tccpg288 over 7 yearsI have updated my code. Can you write the exact line of code that would explain how to call getTotal(), which is in my "Photo" model, from the response.body()?
-
Amir over 7 yearsAdd public getPhoto() in your Model class which return your photo object; just like other getter in your photos class
-
Amir over 7 yearscopy following url in your browser to see response: api.flickr.com/services/rest/…
-
tccpg288 over 7 yearsWhere did you get that URL from? I use the logging interceptor with Retrofit and received the following link: api.flickr.com/services/rest/…