Как десериализировать подкласс в Firebase, используя getValue (Subclass.class)
Я использую новый firebase sdk для android и использую реальную функцию базы данных. Когда я использую getValue(simple.class)
, все в порядке. Но когда я хочу разобрать класс, который является подклассом, все атрибуты материнского класса null
, и я имею этот тип ошибки:
Нет setter/field для имени, найденного в классе 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
, и я получаю
Нет setter/field для атрибута motherAttribute, найденного в классе uk.edume.edumeapp.TestChild
Json, который я разбираю:
{
"childAttribute" : "attribute in child class",
"motherAttribute" : "attribute in mother class"
}
Ответы
Ответ 1
Firebaser здесь
Это известная ошибка в некоторых версиях Firebase Database SDK для Android: наш сериализатор/десериализатор рассматривает свойства/поля только для объявленного класса.
Сериализация унаследованных свойств из базового класса отсутствует в версиях с 9.0 до 9.6 (iirc) SDK Firebase для Android. Он был добавлен обратно в версии с тех пор.
Обход
Тем временем вы можете использовать Jackson (который SDK Firebase 2.x использует под капотом), чтобы заставить модель наследования работать.
Обновить: здесь приведен фрагмент того, как вы можете читать 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()
общедоступной, потому что рассматриваются только общедоступные поля/геттеры. С этим изменением этот 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
немного странно, но, к счастью, это волшебное заклинание, которое можно скопировать/вставить.
Ответ 2
Это, по-видимому, окончательно было исправлено в release 9.6.
Исправлена ошибка, при которой передача производного класса в DatabaseReference # setValue() неправильно сохранила свойства суперкласса.
Ответ 3
для
Нет setter/field для атрибута 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;
}
}
Ответ 4
Отметьте https://firebase.google.com/support/guides/firebase-android
говорится
"Если в вашем JSON есть дополнительное свойство, не входящее в ваш Java-класс, вы увидите это предупреждение в файлах журнала: W/ClassMapper: Нет setter/field для ignoreThisProperty, найденных в классе com.firebase.migrationguide. ChatMessage"
Blockquote
Вы можете избавиться от этого предупреждения, разместив в своем классе аннотацию @IgnoreExtraProperties. Если вы хотите, чтобы база данных Firebase вела себя так, как в SDK 2.x, и генерирует исключение, если есть неизвестные свойства, вы можете поместить аннотацию @ThrowOnExtraProperties в свой класс.
Blockquote