2016-02-10 4 views
2

Я имею json с полем _idИспользование Realm с Gson

String json = "{ _id : 1, name : 'Alex', role: 'admin' }" 

В моей Realm модели я использую @SerializedName атрибут:

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; 
    } 

} 

Если попытаться сохранить JSON:

realm.createOrUpdateObjectFromJson(User.class, json)

Поле _id не может анализироваться и в базе данных создается запись с идентификатором = 0

В документации с использованием @SerializedName атрибута

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); 

В этом случае json = "{ _id : 1, role: 'user' }" просто удалить пользователь name из базы данных, поскольку значение по умолчанию для строки равно нулем.

Итак, возможно, я неправильно использовал атрибут. Как рассмотреть атрибут при работе с методами сохранения json (createOrUpdateObjectFromJson и т. Д.)?

ответ

2

Возможно, вам понадобится гибридное решение, чтобы сделать эту работу. Причина в том, что @SerializedName является аннотацией GSON, а не той, о которой знает Realm. Таким образом, это означает, что у вас есть два варианта, которые вы уже открыли:

1) Используйте GSON, что означает, что конечным результатом является объект с null по умолчанию для name.

2) Используйте createOrUpdateObjectFromJson, что означает, что _id будет проигнорирован, так как для анализатора JSON Realm требуется отображение 1: 1.

Как ни решение будет работать корректно, вы можете изменить их следующим образом:

1) GSON, вместо того, чтобы делать copyToRealmOrUpdate вы можете вручную найти объект и обновить роль:

realm.beginTransaction(); 
realm.where(User.class).equalTo("id", user.getId()).findFirst().setRole(user.getRole()); 
realm.commitTransaction(); 

2) Используя только чистый JSON можно изменить, чтобы соответствовать ожидаемому формату:

JSONObject obj = new JSONObject(json); 
obj.put("id", obj.getString("_id")); 
obj.remove("_id"); 

Realm имеет проблемы отслеживания запрос на таможенной Mappin гс, но она имеет низкий приоритет, как функция, как правило, лучше охвачены такие структуры, как GSON, Jacokson и т.д.: https://github.com/realm/realm-java/issues/1470

+0

спасибо, христианин. Приоритет IMHO должен быть изменен на нормальный :) – Alexandr

5

Почему писать все эти пользовательские сериализаторы когда вы можете сделать Gson и Realm работать вместе с только ОДНА ЛИНИЯ КОДА?

IMO, устанавливая эксклюзивную стратегию каждой модели, которую мы хотим сериализовать это не самый лучший подход.Как вы уже поняли, этот подход требует написания большого количества кода шаблонный, который подвержен ошибкам и хуже всего, убивает то, что Gson о (что делает нашу жизнь менее болезненным).

И так как мы работаем вокруг несовместимостей, почему вы не просто убедитесь, что пройти unmanged RealmObject к вашему Gson сериализатором?

Самое простое решение когда-либо (ИМО) найдено here.

Получить копию в памяти управляемой RealmObject и передать его Gson

new Gson().toJson(realm.copyFromRealm(managedModel)); 

И это все! Больше не нужно писать код!

Other good solutions and explanations are posted here.

Смежные вопросы