Reputation: 5356
My current Android application employs Realm as the local database.
I am populating my Realm entities with data sourced from third party API's.
These API's produce Json response messages which I am persisting to realm using createAllRealm.createAllFromJson(clazz, json)
One of these API's has a response message as shown below
{
"content": [
{
"abstract": "string",
"article_id": 0,
"authors": [
"string"
],
"doi": "string",
"ending_page": "string",
"issue": "string",
"journal_name": "string",
"publisher": "string",
"starting_page": "string",
"title": "string",
"volume": "string",
"year": 0
}
],
"total_number": 0
}
My Realm database object obviously has to have exactly matching field names to ensure all the response data is persisted, e.g.:-
@PrimaryKey
private Long article_id;
private String authors;
private Long year;
private Long ending_page;
private Long starting_page;
private String _abstract;
private String doi;
private String issue;
private String journal_name;
private String publisher;
private String title;
private String volume;
As the message contains a Json field name that is a Java keyword e.g. "abstract" I have to name my java field _abstract.
When I persist these messages _abstract is always null as the Json and Java field names do not match.
Does Realm have any way I can resolve this issue and still employ createAllFromJson?
Or will I have to use Jackson or GSON to convert the Json message to Java objects before I can persist the response data?
Upvotes: 0
Views: 826
Reputation: 756
there is a workaround mentioned in https://github.com/realm/realm-java/issues/1470
Until this issue is resolved I have made a workaround in my App, let's say I have Chat.java
public class Chat extends RealmObject {
@Index
@SerializedName("c")
private String code = "";
@Index
@SerializedName("t")
private int type;
}
And RealmUtil.java
public class RealmUtil {
private static HashMap<String, HashMap<String, String>> classesFieldsMap = new HashMap<>();
static {
initClasses(Chat.class);
}
private static void initClasses(Class cls) {
if (!classesFieldsMap.containsKey(cls.toString())) {
Field[] fields = cls.getDeclaredFields();
HashMap<String, String> fieldsMap = new HashMap<>();
for (Field a : fields) {
SerializedName annotation = a.getAnnotation(SerializedName.class);
if (annotation != null) {
fieldsMap.put(annotation.value(), a.getName());
}
}
classesFieldsMap.put(cls.toString(), fieldsMap);
}
}
public static JSONObject mapGsonObjectToRealm(Class cls, JSONObject object) throws JSONException {
JSONObject newUserObj = new JSONObject();
HashMap<String, String> fieldsMap = classesFieldsMap.get(cls.toString());
for (String setKey : fieldsMap.keySet()) {
String mappedKey = fieldsMap.get(setKey);
if (object.has(setKey))
newUserObj.put(mappedKey, object.get(setKey));
}
return newUserObj;
}
}
By using reflection initClasses method will map each of the Gson SerializedName of the class to the corresponding names for Realm record.
And mapGsonObjectToRealm method will create a new object of the old one with new fields names.
Usage:
JSONObject newObject = RealmUtil.mapGsonObjectToRealm(Chat.class, new JSONObject().put("c", "this_is_code").put("t", "this_is_type"));
final JSONArray jsonArray = new JSONArray();
jsonArray.put(newObject);
Realm.getDefaultInstance().executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.createOrUpdateAllFromJson(Chat.class, jsonArray);
}
});
Upvotes: 1
Reputation: 756
try using @SerializedName annotation
@SerializedName("abstract")
private String _abstract;
this annotation comes under google gson annotations package, so may need to add gson dependancy
Upvotes: 1