Как использовать автоматическое значение с firebase 9.2 в Android

Я хочу использовать автоматическое значение с firebase 9.2.0+. У меня есть следующий код:

@AutoValue
public abstract class Office {

    public static Builder builder() {
        return new AutoValue_Office.Builder();
    }

    public abstract double latitud();
    public abstract double longitud();

    @AutoValue.Builder
    public static abstract class Builder {

        public abstract Builder latitud(double latitud);
        public abstract Builder longitud(double longitud);

        public abstract Office build();

    }

}

Но когда я вызываю это Office office = childDataSnapshot.getValue(Office.class);, я получаю эту ошибку:

com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office

У кого-нибудь есть идея, почему я получаю эту ошибку и как ее решить? Я читал, что firebase больше не использует jackson для сериализации json. Поэтому я не уверен, как указать тип @JsonProperty("latitud"), который я использовал @PropertyName безуспешно.

Я также попытался переименовать абстрактные методы, такие как public abstract double getLatitud();, и после этого ошибка следующая:

java.lang.InstantiationException: Can't instantiate abstract class com.example.app.model.Office

Поэтому я не уверен, как это решить.

РЕШЕНИЕ

Благодаря hatboysam и Frank van Puffelen я, наконец, смог решить эту проблему со следующим решением.

  1. Я создал перечисление FirebaseUtil с двумя методами сериализации и десериализации объектов для Firebase на основе hatboysam ответ и комментарий Фрэнка ван Пуффелена.
  2. Я создаю пару классов User и Phone для тестирования.
  3. Зависимости:

    compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.0'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.8.0'
    
  4. Пример использования:

    User user = FirebaseUtil.deserialize(dataSnapshot, User.class);
    Map<String, Object> map = FirebaseUtil.serialize(user);
    

person epool    schedule 08.07.2016    source источник
comment
Один вопрос: какова цель использования Auto-Value? Для создания Parcelable?   -  person Chintan Soni    schedule 08.07.2016


Ответы (2)


Я не уверен, что это возможно с картографом данных Firebase по умолчанию, но есть возможный обходной путь. Сначала давайте объясним ошибки, которые вы видите:

com.google.firebase.database.DatabaseException: свойства для сериализации не найдены в классе com.example.app.model.Office

Сопоставитель Firebase ищет либо поля public, либо поля, названные по шаблону getFoo/setFoo. Итак, в вашем классе маппер не видит никаких свойств.

java.lang.InstantiationException: невозможно создать экземпляр абстрактного класса com.example.app.model.Office

Это тот, который, я думаю, вам будет трудно обойти. Чтобы десериализация работала, ваш класс должен иметь общедоступный конструктор без аргументов, который преобразователь может вызывать через отражение (newInstance()). Насколько я знаю, это не то, как работает AutoValue.

Но не теряйте надежды!. Согласно этой проблеме с github, существует способ сделать Jackson и AutoValue совместимым с помощью аннотации @JsonCreator. . Поэтому вам нужно будет использовать и Джексон, и Firebase, чтобы выполнить эту работу.

Сериализация:

// Convert to a Map<String,Object> using Jackson and then pass that to Firebase
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = mapper.convertValue(office, Map.class);
databaseReference.setValue(map);

Десериализация:

// Use Firebase to convert to a Map<String,Object>
GenericTypeIndicator<Map<String,Object>> t = new GenericTypeIndicator<Map<String,Object>>() {};
Map<String,Object> map = dataSnap.getValue(t);

// Use Jackson to convert from a Map to an Office object
ObjectMapper mapper = new ObjectMapper();
Office pojo = mapper.convertValue(map, Office.class);
person Sam Stern    schedule 08.07.2016
comment
Да, извините, я забыл упомянуть, что я безуспешно пробовал этот обходной путь, так как я мог читать/исследовать, что firebase больше не использует Джексона. Так что этот обходной путь не работает для меня:/ - person epool; 08.07.2016
comment
@epool, что именно в этом обходном пути не работает для вас? Хотя Firebase больше не использует Джексона внутри себя, вы все равно можете использовать Джексона в качестве компаньона для firebase. - person Sam Stern; 08.07.2016
comment
Чтобы узнать, как использовать Джексона с последними SDK Firebase, см. stackoverflow.com/questions/37547399/ - person Frank van Puffelen; 08.07.2016
comment
Неважно, я пробовал неправильный код. Я обновлю свой вопрос своим решением. Большое вам спасибо за помощь, ребята! - person epool; 10.07.2016

Я написал для этого расширение AutoValue:

https://github.com/mattlogan/auto-value-firebase

Расширение создает совместимый с firebase класс с именем FirebaseValue в качестве статического внутреннего класса в созданном вами классе AutoValue. Вы можете преобразовать свой класс AutoValue в класс FirebaseValue с помощью сгенерированных конструкторов.

Вот пример, скопированный из readme, как это выглядит:

@AutoValue @FirebaseValue
public abstract class Taco {

  public static Taco create(String name, List<Ingredient> ingredients, Review review) {
    return new AutoValue_Taco(name, ingredients, review);
  }

  // Create AutoValue_Taco instance from AutoValue_Taco.FirebaseValue instance
  public static Taco create(DataSnapshot dataSnapshot) {
    AutoValue_Taco.FirebaseValue taco = dataSnapshot.getValue(AutoValue_Taco.FirebaseValue.class);
    return new AutoValue_Taco(taco);
  }

  // Create AutoValue_Taco.FirebaseValue instance from AutoValue_Taco instance
  public Object toFirebaseValue() {
    return new AutoValue_Taco.FirebaseValue(this);
  }

  public abstract String name();

  public abstract List<Ingredient> ingredients();

  public abstract Review review();
}
person Matt Logan    schedule 13.08.2016
comment
Хороший! звучит очень хорошо! Посмотрю на выходных, молодец! :) - person epool; 13.08.2016
comment
Поддерживает ли он Firestore и DocumentSnapshot? - person Aegir; 15.01.2019
comment
@Aegir Извините, нет. Я перешел на Kotlin некоторое время назад и с тех пор не использовал AutoValue! Если вы ищете проект с открытым исходным кодом, не стесняйтесь открывать PR :) - person Matt Logan; 15.01.2019