I have json
with field _id
String json = "{ _id : 1, name : 'Alex', role: 'admin' }"
In my Realm model I use @SerializedName
attribute:
public class User extends RealmObject {
@SerializedName("_id")
@PrimaryKey
private int id;
private String name;
private String comment;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}
If try save the json:
realm.createOrUpdateObjectFromJson(User.class, json)
field _id
can't parsed and in database created record with id = 0
In docs using @SerializedName
attribute
Gson gson = 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;
}
}).create();
User user = gson.fromJson(json, User.class);
realm.beginTransaction();
realm.copyToRealmOrUpdate(user);
In this case json = "{ _id : 1, role: 'user' }"
just remove user name
from database, because default value for String is null.
So, probably I incorrectly using the attribute. How to consider the attribute when dealing with the methods of conservation of json (createOrUpdateObjectFromJson
, etc)?
Why writing all these custom serializers when you can make Gson and Realm work together with just ONE LINE OF CODE?
IMO, setting an exclusive strategy to every model we want to serialize is not the best approach. As you have realized, this approach requires writing a lot of boiler-plate code which is error prone and the worst of all, kills what Gson is about (which is making our lives less painful).
And since we're working-around incompatibilities, why don't you just make sure to pass an unmanged RealmObject to your Gson serializer?
Found here. Get a copy in memory of the managed RealmObject and pass it to Gson
new Gson().toJson(realm.copyFromRealm(managedModel));
And that's it! No more code to write!
Other good solutions and explanations are posted here.
You probably need a hybrid solution in order to make this work. The reason is that @SerializedName
is a GSON annotation and not one that Realm knows about. So this means you have two choices as you already discovered:
1) Use GSON, which means the end result is an object with null
as the default for name
.
2) Use createOrUpdateObjectFromJson
which means that _id
will be ignored because Realm's JSON parser require a 1:1 mapping.
As neither solution will work correctly you can modify them in the following way:
1) With GSON, instead of doing copyToRealmOrUpdate
you can manually search for the object and update the role:
realm.beginTransaction();
realm.where(User.class).equalTo("id", user.getId()).findFirst().setRole(user.getRole());
realm.commitTransaction();
2) Using just the pure JSON you can modify to match the expected format:
JSONObject obj = new JSONObject(json);
obj.put("id", obj.getString("_id"));
obj.remove("_id");
Realm has an issue tracking the request for custom mappings, but it has a low priority as that feature is usually better covered by frameworks such as GSON, Jacokson, etc. : https://github.com/realm/realm-java/issues/1470
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With