Search code examples
androidgsonparceler

Missing fields when unwrapping a Parcel object with Parceler library


I have a Java Bean class, annotated with @Parcel(Parcel.Serialization.BEAN) and Gson's @SerializedName on some fields:

Question.java:

@Parcel(Parcel.Serialization.BEAN)
public class Question {

    private Integer id;
    private String title;
    private String description;
    private User user;

    @SerializedName("other_model_id")
    private Integer otherModelId,

    @SerializedName("created_at")
    private Date createdAt;

    // ----- Getters and setters -----
}

When I'm starting ShowQuestionActivity, I pass my Parceled question object to it (where question has all fields set):

Intent intent = new Intent(context, ShowQuestionActivity.class);
intent.putExtra("extra_question", Parcels.wrap(question));
startActivity(intent);

On ShowQuestionActivity, I get "extra_question" from my intent object:

Question question = Parcels.unwrap(intent.getParcelableExtra(Constants.EXTRA_QUESTION));

But Parceler returns me only title and description (Strings)... All other fields are null.

Wrapping the object with Parcels.wrap(question) and unwrapping it with Parcels.unwrap(question) on debugger works perfectly, but after passing it through intent, it seems to "lose" its values, but I can't find the problem...


My Parceler setup is the following:

Module build.gradle:

dependencies {
    compile 'org.parceler:parceler-api:1.1.4'
    apt 'org.parceler:parceler:1.1.4'
}

And in my project's build.gradle:

dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}

Solution

  • With the BEAN serialization strategy, Parceler requires matching getter and setters for each property in the class that you want to be wrapped and unwrapped.

    In addition properties that aren't mapped by default, like Date, require you to write a converter or map these types in with @ParcelClass. See http://parceler.org/#custom_serialization

    Here's a code example:

    @Parcel(Parcel.Serialization.BEAN)
    public class Question {
    
        private Integer id;
        private String title;
        private Date createdAt;
    
        // id is included in the Parcelable because it has matching getter and setters
        public Integer getId() { return id; }
        public void setId(Integer id) { this.id = id; }
    
        // title is not included as the setter is missing (it's not a true bean property)
        public String getTitle() { return title; }
    
        // createdAt will issue an error as it is not a defined type, and no converter is defined.
        public Date getCreatedAt() { return createdAt; }
        public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; }   
    }
    

    Worth noting, if you're happy with Gson marshalling your internal class state, you may want to consider using the default FIELD serialization strategy instead of BEAN paired with non-private fields. This technique will not require any specific getter and setters combination.