How to deserialise a subclass in Firebase using ge

2019-01-01 16:03发布

I'm using the new firebase sdk for android and use the real database feature. When i use the getValue(simple.class) everything is fine. But when i want to parse a class which is a subclass, all the attribute of the mother class are null, and i have this type of error:

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

this function

snapshot.getValue(TestChild.class);

motherAttribute attribute is null, and I get

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

the Json that i parse is:

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

4条回答
何处买醉
2楼-- · 2019-01-01 16:31

Firebaser here

This is a known bug in some versions of the Firebase Database SDK for Android: our serializer/deserializer only considers properties/fields on the declared class.

Serialization of inherited properties from the base class, is missing in the in releases 9.0 to 9.6 (iirc) of the Firebase Database SDK for Android. It was added back in versions since then.

Workaround

In the meantime you can use Jackson (which the Firebase 2.x SDKs used under the hood) to make the inheritance model work.

Update: here's a snippet of how you can read from JSON into your 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;
    }
}

You'll note that I made getParentAttribute() public, because only public fields/getters are considered. With that change, this JSON:

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

Becomes readable with:

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

The GenericTypeIndicator is a bit weird, but luckily it's a magic incantation that can be copy/pasted.

查看更多
余欢
3楼-- · 2019-01-01 16:41

Check this https://firebase.google.com/support/guides/firebase-android

it says

"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

You can get rid of this warning by putting an @IgnoreExtraProperties annotation on your class. If you want Firebase Database to behave as it did in the 2.x SDK and throw an exception if there are unknown properties, you can put a @ThrowOnExtraProperties annotation on your class.

Blockquote

查看更多
时光乱了年华
4楼-- · 2019-01-01 16:42

This was apparently finally fixed in release 9.6.

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

查看更多
像晚风撩人
5楼-- · 2019-01-01 16:46

for:

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

put setter for TestChild class:

 public class  TestMother {

     private String motherAttribute;

     public String getMotherAttribute() {
         return motherAttribute;
     }

     //set
     public void setMotherAttribute(String motherAttribute) {
         this.motherAttribute= motherAttribute;
     }
 }
查看更多
登录 后发表回答