Как десериализовать подкласс в Firebase, используя getValue(Subclass.class)

Я использую новый Firebase SDK для Android и использую реальную функцию базы данных. Когда я использую getValue(simple.class) Все отлично. Но когда я хочу проанализировать класс, который является подклассом, все атрибуты родительского класса nullи у меня есть этот тип ошибки:

Не найдено сеттера / поля для имени в классе uk.edume.edumeapp.TestChild

public class TestChild  extends TestMother {

    private String childAttribute;

    public String getChildAttribute() {
        return childAttribute;
    }
}

public class TestMother {

    protected String motherAttribute;

    protected String getMotherAttribute() {
        return motherAttribute;
    }
}

эта функция

snapshot.getValue(TestChild.class);

motherAttribute атрибут nullи я получаю

Не найден сеттер / поле для motherAttribute в классе uk.edume.edumeapp.TestChild

JSON, который я анализирую:

{
  "childAttribute" : "attribute in child class",
  "motherAttribute" : "attribute in mother class"
}

4 ответа

Решение

Firebaser здесь

Это известная ошибка в некоторых версиях Firebase Database SDK для Android: наш сериализатор / десериализатор рассматривает только свойства / поля в объявленном классе.

Сериализация унаследованных свойств базового класса отсутствует в выпусках 9.0–9.6 (iirc) пакета Firebase Database SDK для Android. С тех пор он был добавлен в версии.

Временное решение

В то же время вы можете использовать Jackson (который использовался в Firebase 2.x SDK под капотом), чтобы заставить работать модель наследования.

Обновление: вот фрагмент того, как вы можете читать из JSON в свой TestChild:

public class TestParent {
    protected String parentAttribute;

    public String getParentAttribute() {
        return parentAttribute;
    }
}
public class TestChild  extends TestParent {
    private String childAttribute;

    public String getChildAttribute() {
        return childAttribute;
    }
}

Вы заметите, что я сделал getParentAttribute() public, потому что рассматриваются только открытые поля / получатели. С этим изменением этот JSON:

{
  "childAttribute" : "child",
  "parentAttribute" : "parent"
}

Становится читаемым с:

ObjectMapper mapper = new ObjectMapper();
GenericTypeIndicator<Map<String,Object>> indicator = new GenericTypeIndicator<Map<String, Object>>() {};
TestChild value = mapper.convertValue(dataSnapshot.getValue(indicator), TestChild.class);

GenericTypeIndicator немного странно, но, к счастью, это волшебное заклинание, которое можно копировать / вставлять.

Это было окончательно исправлено в выпуске 9.6.

Исправлена ​​ошибка, из-за которой передача производного класса в DatabaseReference#setValue() некорректно сохраняла свойства из суперкласса.

За:

Не найден сеттер / поле для motherAttribute в классе uk.edume.edumeapp.TestChild

установить сеттер для класса TestChild:

 public class  TestMother {

     private String motherAttribute;

     public String getMotherAttribute() {
         return motherAttribute;
     }

     //set
     public void setMotherAttribute(String motherAttribute) {
         this.motherAttribute= motherAttribute;
     }
 }

Проверьте это https://firebase.google.com/support/guides/firebase-android

это говорит

"Если в вашем JSON есть дополнительное свойство, которого нет в вашем классе Java, вы увидите это предупреждение в файлах журнала: W/ClassMapper: не найден параметр / поле для ignoreThisProperty для класса com.firebase.migrationguide.ChatMessage"

Blockquote

Вы можете избавиться от этого предупреждения, поместив аннотацию @IgnoreExtraProperties в свой класс. Если вы хотите, чтобы база данных Firebase вела себя так же, как в 2.x SDK, и выдает исключение, если есть неизвестные свойства, вы можете добавить аннотацию @ThrowOnExtraProperties для вашего класса.

Blockquote

Другие вопросы по тегам