如何使用 getValue(Subclass.class) 在 Firebase 中反序列化子类

How to deserialise a subclass in Firebase using getValue(Subclass.class)

我正在为 android 使用新的 firebase sdk 并使用真正的数据库功能。当我使用 getValue(simple.class) 时,一切都很好。但是当我想解析一个class是一个子class时,母亲class的所有属性都是null,我有这种类型的错误:

No setter/field for name found on class 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,我得到

No setter/field for motherAttribute found on class uk.edume.edumeapp.TestChild

我解析的Json是:

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

用于:

No setter/field for motherAttribute found on class uk.edume.edumeapp.TestChild

将 setter 用于 TestChild class:

 public class  TestMother {

     private String motherAttribute;

     public String getMotherAttribute() {
         return motherAttribute;
     }

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

这里是 Firebaser

这是 Android 的某些版本的 Firebase 数据库 SDK 中的一个已知错误:我们的 serializer/deserializer 仅考虑声明的 class 上的 properties/fields。

Android 的 Firebase 数据库 SDK 9.0 至 9.6 (iirc) 版中缺少从基础 class 继承的属性的序列化。从那时起,它又被添加回了版本。

解决方法

同时,您可以使用 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,因为只考虑了 public fields/getters。有了这个改变,这个 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有点奇怪,还好是个神奇的咒语,可以copy/pasted。

勾选这个https://firebase.google.com/support/guides/firebase-android

它说

"If there is an extra property in your JSON that is not in your Java class, you will see this warning in the log files: W/ClassMapper: No setter/field for ignoreThisProperty found on class com.firebase.migrationguide.ChatMessage "

Blockquote

您可以通过在 class 上添加 @IgnoreExtraProperties 注释来消除此警告。如果您希望 Firebase 数据库的行为与在 2.x SDK 中一样,并在存在未知属性时抛出异常,您可以在 class.

上添加 @ThrowOnExtraProperties 注释

Blockquote

这显然最终在 release 9.6 中得到修复。

Fixed an issue where passing a derived class to DatabaseReference#setValue() did not correctly save the properties from the superclass.