You might know about Realm, a fancy and practical storage option that one can use on Android. Realm is quite fast and it is really easy to work with but recently I had to parse some data from the webservice and I wanted to use GSON, the Android Json parser library. All works well if you do what it writes here but there is a problem on Realm when you want to store a list of Strings or Integers into your model. You just can’t!
The workaround/suggestion is to create a wrapper over String and use a list of that instead (which is not too nice/intuitive/etc.).
Given that, I had to created the following wrapper class:
/**
* Created by catalin prata on 29/05/15.
*
* Wrapper over String to support setting a list of Strings in a RealmObject
* To use it with GSON, please see RealmStringDeserializer
*
*/
public class RealmString extends RealmObject {
private String stringValue;
public RealmString(){}
public RealmString(String stringValue){
this.stringValue = stringValue;
}
public String getStringValue() {
return stringValue;
}
public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}
}
So we have our class using RealmList<RealmString> :
/**
* Created by catalinprata on 29/05/15.
*/
public class MyCustomClass extends RealmObject {
private RealmList<RealmString> strings;
public RealmList<RealmString> getStrings() {
return strings;
}
public void setStrings(RealmList<RealmString> strings) {
this.strings = strings;
}
}
Ok, nice, now I can set a List of RealmString objects to my entity that has a list of Strings.
Now we need to tell GSON that we have that crappy workaround so it can see it as a list of Strings, I’ve done that by doing a custom deserializer and implementing JsonDeserializer like this:
/**
* Created by catalin prata on 29/05/15.
* <p/>
* Used to deserialize a list of realm string objects
*/
public class RealmStringDeserializer implements
JsonDeserializer<RealmList<RealmString>> {
@Override
public RealmList<RealmString> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
RealmList<RealmString> realmStrings = new RealmList<>();
JsonArray stringList = json.getAsJsonArray();
for (JsonElement stringElement : stringList) {
realmStrings.add(new RealmString(stringElement.getAsString()));
}
return realmStrings;
}
}
Ok, now we have the String wrapper and the GSON deserializer, the final thing would be to se the deserializer on the GsonBuilder before parsing the Json.
// the exclusion is for the Realm stackoverflow crash
GsonBuilder gsonBuilder = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
});
// register the deserializer
gsonBuilder.registerTypeAdapter(new TypeToken<RealmList<RealmString>>() {
}.getType(), new RealmStringDeserializer());
Gson gson = gsonBuilder.create();
// parse the Json
MyCustomClass myObject = gson.fromJson(reader, MyCustomClass.class);
And it should work just fine :P
