2

I'm managing a database using an abstract class which has a bunch of handy convenience methods. In particular, it has insert(Context), update(Context) and delete(Context) which means you can create a bunch of different objects that inherit this class, all of which have their own database mappings, and just update or insert them one by one.

Another developer has added GSON deserialization markup to this structure. This is working fine, except that the update function relies on comparing objects' unique identifiers; the particular thing that's used as an identifier varies from object to object. This means that while the superclass, which has the update(...) method in, has

@SerializedName("id")
protected String mUUID;

the subclass would need a different mapping.

Currently I'm solving this by overriding the update(...) method in the subclass to compare using a different identifying field, but this is pretty unsatisfying. Is it possible to map a different serialized name to a superclass field in GSON, and if so, how do you do it?

To clarify, the class structure is roughly

public abstract class DatabasePersistent {
    //...
    @SerializedName("id")
    protected String mUUID;
    //...
    public int update(Context context) {
        return context.getContentResolver().update(
                getContentProviderURI(), //abstract, allows objects to update the right table 
                toContentValues(), //abstract, converts the object to a ContentValues
                UUID_EQUALS, //this is a where clause string
                new String[]{mUUID}
        );
    }
}

I want to make a

public class Thing extends DatabasePersistent {
    //all the abstract implementations
    //and so on
}

which somehow changes the mapping of mUUID so I can use the same primary ID machinery as in the superclass (eg the update method) but have different fields in the incoming JSON identify different objects.

Andrew Wyld
  • 7,133
  • 7
  • 54
  • 96
  • 1
    i am not sure I really get the complete problem (may be a little more code with the different ids and how they relate to gson?) but it seems to me that you could define a `getId` method in your superclass, and override the method in the subclass to return the field you want to use as identifier. – njzk2 Jul 25 '14 at 15:28
  • That's a really nice idea, but sadly it's telling me "attribute value must be constant" (I sort of thought it might, but even so, ingenious thought). – Andrew Wyld Jul 25 '14 at 15:37
  • 1
    what I am saying is that you could use `new String[]{getId()}` in the update method instead of `new String[]{mUUID}`, and have a default implementation `public String getId() { return mUUID; }` for example – njzk2 Jul 25 '14 at 15:45
  • Oh, *now* I get it. Yeah, that would work. I'm genuinely curious to know if you can change a deserialization mapping like this, though, because it seems to me it would be a really useful thing to be able to do. – Andrew Wyld Jul 25 '14 at 15:47
  • i don't think you can really change the deserialization mapping, but you probably can abstract the field use for object identification in the database. (I realize now that you possibly need to change `UUID_EQUALS` to match the name of the field) – njzk2 Jul 25 '14 at 15:49
  • Oh, yeah—that's basically what I *have* done. Thanks! – Andrew Wyld Jul 25 '14 at 15:51
  • 1
    @alobodzk posted an interesting comment under their answer, which I paste here : > It would be much easier if GSON would allow to use `@Expose` on methods, then you would annotate getId() accessor. To bypass that you can either use this bad boy: http://github.com/julman99/gson-fire or implement your JsonSerializer object, that would call that method for you. – njzk2 Jul 25 '14 at 15:58

1 Answers1

1

I take it Thing will have attributes, like String customID, String foo, String bar that are mapped from the incoming JSON?

If you could somehow override the setter for each of those Thing member vars - perhaps a lifecycle event, or perhaps if you provide a setCustomID(String customID) in your class GSON will use it vs. the annotation? then you can simply call super.setId(customID).

This is like a "dynamic" or "calculated" field.

This post suggests GSON are unlikely to support property set/get though.

Why does GSON use fields and not getters/setters?

Community
  • 1
  • 1
PorridgeBear
  • 1,183
  • 1
  • 12
  • 19