1

I'm trying to create an Photos ArrayList of Photo objects. I want to separate the Photo class from the Photos class because it's becoming unreadable. The problem is that I'm no longer getting any data back

It is worth noting that this WAS working when I had the Photo class nested in Photos class as follows:

public class Photos { 
    @Expose private int page;
    @Expose private int pages;
    @Expose private int perpage;
    @Expose private String total;
    @Expose private ArrayList<Photo> photo = new ArrayList<Photo>();

    //helpers 
    public ArrayList<Photo> getPhotos(){return photo;}
    public void setPhotos(ArrayList<Photo> photos){this.photo = photos;}

//want to put this in it's own class
public class Photo { 
    //helpers 
    @Override 
    public String toString(){
        return title;
    } 
    public String getUrl(){return url_s;}

    //GSON fields 
    @Expose private String id;
    @Expose private String owner;
    @Expose private String secret;
    @Expose private String server;
    @Expose private int farm;
    @Expose private String title;
    @Expose private int ispublic;
    @Expose private int isfriend;
    @Expose private int isfamily;
    @Expose private String url_s;
} 

}

Retrofit:

 new Callback<PhotosResponse>() {
                    @Override
                    public void success(PhotosResponse photosResponse, Response response) {
                    bus.post(new ImagesReceivedEvent(photosResponse.getPhotosObject().getPhotos()));
                }

The parameters matched the JSON exactly and I received an arraylist through the following response:

public class ImagesReceivedEvent {

    private ArrayList<Photo> result;

    public ImagesReceivedEvent(ArrayList<Photo> result){
        Log.i(TAG, "arraylist for presenter");
        this.result = result;
    }

    public ArrayList<Photo> getResult(){return result;}
}

This is where the response was received, but no longer:

public class PhotosResponse {

    @Expose private Photos photos;
    @Expose private String stat;

    public Photos getPhotosObject(){return photos;}

    public void setPhotosObject(Photos photos) {
        this.photos = photos;
    }

    public String getStat() {
        return stat;
    }

    public void setStat(String stat) {
        this.stat = stat;
    }
}

How can I separate these classes and still get the arrayList as a response? I want to separate them because I plan on using Parcelable on each class there are some hurdles I'd need to jump over when having the inner class. Any guidance would be much appreciated! Thanks.

Edit: Here is the JSON payload:

{ "photos": { "page": 1, "pages": 10, "perpage": 100, "total": "1000", 
"photo": [
  { "id": "18473086614", "owner": "130897025@N07", "secret": "b3c684c356", "server": "259", "farm": 1, "title": "My travels circa 2013. Summer days on #charlesbridge #charlesbridgeprague #prauge. upbound@upbound.net || 718-754-5850 #photographer #photography #canonphotography #canon #canondslr #canon600d #dslr #600d #travelphotography #europe #upboundonline #canonre", "ispublic": 1, "isfriend": 0, "isfamily": 0 },
  { "id": "18473090744", "owner": "131790787@N07", "secret": "2734055852", "server": "3705", "farm": 4, "title": "Untitled", "ispublic": 1, "isfriend": 0, "isfamily": 0 },
  { "id": "18473091934", "owner": "61308696@N00", "secret": "b40dbfcf15", "server": "401", "farm": 1, "title": "Climbing Acatenango", "ispublic": 1, "isfriend": 0, "isfamily": 0 },
  { "id": "18473092714", "owner": "39055811@N08", "secret": "e51f5a183b", "server": "3936", "farm": 4, "title": "DSCF1735.jpg", "ispublic": 1, "isfriend": 0, "isfamily": 0 }
] }, "stat": "ok" }
Futureproof
  • 375
  • 4
  • 21
  • Can you post the JSON (an example body) you want deserialized? – Eric Cochran Jun 23 '15 at 20:56
  • I can't quite tell what you are asking. Are you saying that you think Gson stopped deserializing correctly when you remove your inner nested class? – Eric Cochran Jun 24 '15 at 01:17
  • Exactly. It was working before (as described in the above photos class with nested photo), but I moved the photo class out into its own class and it stopped working. It might be an education problem. – Futureproof Jun 24 '15 at 01:44
  • Something else is the problem. Gson does not care if it is an inner class or not. Sorry... – Eric Cochran Jun 24 '15 at 01:45
  • Possible duplicate of [Unfortunately MyApp has stopped. How can I solve this?](http://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this) – Futureproof Nov 29 '15 at 02:49

2 Answers2

1

It turns out that I made a mistake on the naming convention:

@Expose private ArrayList<Photo> mPhotos = new ArrayList<Photo>();

I had renamed photo to mPhotos on the arrayList but forgot that GSON needs the EXACT names of the JSON fields (Which is originally photo). I changed it back to "photo" and now the arrayList populates on my Photos object.

I need to emphasize to myself that all fields MUST match the JSON naming convention.

Thanks.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Futureproof
  • 375
  • 4
  • 21
0

When using Retrofit and GSON there's no way to "separate" your response into different classes, you must later do it yourself. Receive your big object with all the info, then unwrap it to the needed classes.

On a project I did I had a specific package with Wrapper classes to get responses from Retrofit, then later I'd manually map it to the Objects I actually needed. Hope it helps.

Teo Inke
  • 5,928
  • 4
  • 38
  • 37
  • You should have defined your own TypeAdapter. Don't make Java objects just because the API response doesn't match you pojos. – Eric Cochran Jun 23 '15 at 20:55
  • I honestly find it way easier to create Wrapper classes instead of writing a custom Adapter. – Teo Inke Jun 23 '15 at 20:57
  • It's a call you have to make. Making wrapper classes adds code complexity and inefficiency, but writing a custom TypeAdapter takes more dev time initially. – Eric Cochran Jun 23 '15 at 21:01
  • Adds code complexity and inefficiency? Tell me more about that – Teo Inke Jun 23 '15 at 21:12
  • Code complexity: you said it yourself. It's a wrapper. You are not making the ideal Java object for your code's use case because you are making it fit with the JSON payload. Inefficiency: Java objects are not cheap allocations. If you really just needed one Java object to define your data, that's going to hurt when you divide it into three objects and scale to thousands of objects. – Eric Cochran Jun 23 '15 at 21:18
  • I believe unwraping the big object into the needed classes is what I'm currently doing. Is it possible though, that the wrapper can be defined in separate classes, not nested, for this purpose? – Futureproof Jun 23 '15 at 21:26
  • The beauty of Retrofit and GSON is that it does all the hard work for you. Creating a wrapper class takes up to 10 lines of code, instead of reinventing the wheel. What you mentioned is not relevant inefficiency imho. – Teo Inke Jun 23 '15 at 21:28
  • Yes, and as I mentioned you can even define the big object in a different package so it doesn't get messy – Teo Inke Jun 23 '15 at 21:29
  • Am I missing something then? I've defined the objects in two classes but the GSON no longer works. – Futureproof Jun 24 '15 at 14:09
  • Use only the class that contains the whole response, say, Response, and make sure it matches your JSON structure. Create the two separate objects in a different package, and as soon as you receive your Response, you unwrap it and assign your objects to other classes (Photos, List, etc). – Teo Inke Jun 24 '15 at 15:03