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