1

I'm trying to Query Firebase data and store it into the Dinosaur class from the example link below. I have an issue when importing directly from Firebase into the Dinosaur Facts class. It's able to create the Query and enters the "onChildAdded" method. It then goes to the Dinosaur constructor class but crashes right after that.

DinosaurFacts facts = snapshot.getValue(DinosaurFacts.class); //CRASHES HERE

https://www.firebase.com/docs/android/guide/retrieving-data.html

Here is DinosaurFacts class

package jobsme.com.firebasequery;

import android.util.Log;

public class DinosaurFacts {
    long height;
    double length;
    long weight;

    public DinosaurFacts() {
        Log.i("MyActivity", "FIIIIIIIIIIIIIIIIIINDMEEEE2");
        // empty default constructor, necessary for Firebase to be able to deserialize blog posts
    }

    public long getHeight() {
        Log.i("MyActivity", "FIIIIIIIIIIIIIIIIIINDMEEEE3");
        return height;
    }

    public double getLength() {
        return length;
    }

    public long getWeight() {
        return weight;
    }

}

Here is the onCreate method in the MainAcitivity

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Firebase.setAndroidContext(this);

    Firebase ref = new Firebase("https://dinosaur-facts.firebaseio.com/dinosaurs");
    Query queryRef = ref.orderByChild("height");

    queryRef.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot snapshot, String previousChild) {
            Log.i("MyActivity", "onChildAdded");
            DinosaurFacts facts = snapshot.getValue(DinosaurFacts.class);
            Log.i("MyActivity", snapshot.getKey() + " was " + facts.getHeight() + " meters tall");
        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {

        }
        // ....
    });

    Log.i("MyActivity", "FIIIIIIIIIIIIIIIIIINDMEEEE");


}

The query is successful but the importing crashes. Hopefully that means I setup everything correctly?

Here's the log output:

12-11 16:48:37.793 5581-5581/jobsme.com.firebasequery E/AndroidRuntime: FATAL EXCEPTION: main
Process: jobsme.com.firebasequery, PID: 5581
com.firebase.client.FirebaseException: Failed to bounce to type
    at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:196)
    at jobsme.com.firebasequery.MainActivity$2.onChildAdded(MainActivity.java:45)
    at com.firebase.client.core.ChildEventRegistration$1.run(ChildEventRegistration.java:50)
    at com.firebase.client.core.view.EventRaiser$1.run(EventRaiser.java:37)
    at android.os.Handler.handleCallback(Handler.java:733)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5001)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
    at dalvik.system.NativeStart.main(Native Method)
 Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "vanished" (class jobsme.com.firebasequery.DinosaurFacts), not marked as ignorable (3 known properties: , "weight", "length", "height"])
    at [Source: java.io.StringReader@52851428; line: 1, column: 33] (through reference chain: jobsme.com.firebasequery.DinosaurFacts["vanished"])
    at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:555)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:708)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1160)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:315)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
    at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:192)
    at jobsme.com.firebasequery.MainActivity$2.onChildAdded(MainActivity.java:45) 
    at com.firebase.client.core.ChildEventRegistration$1.run(ChildEventRegistration.java:50) 
    at com.firebase.client.core.view.EventRaiser$1.run(EventRaiser.java:37) 
    at android.os.Handler.handleCallback(Handler.java:733) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:136) 
    at android.app.ActivityThread.main(ActivityThread.java:5001) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:515) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 
    at dalvik.system.NativeStart.main(Native Method)     
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

3

This is the JSON for one of the dinosaurs in that database:

"bruhathkayosaurus": {
  "appeared": -70000000,
  "height": 25,
  "length": 44,
  "order": "saurischia",
  "vanished": -70000000,
  "weight": 135000
},

The DinosaurFacts class you're using only has fields+getters for these properties: height, length, weight. So when the Firebase tries to deserialize the JSON into a DinosaurFacts object, it complains about the unmapped properties.

The simplest way to get rid of the error is by telling Jackson (which Firebase uses internally to map between JSON and Java) to ignore any unmapped properties it encounters in the JSON:

@JsonIgnoreProperties(ignoreUnknown = true)
public static class DinosaurFacts {

But be careful with this. If you now write a DinosaurFacts object back into the database, it will only have height, length and weight properties. It will not have: appeared, order or vanished. In fact: even if the properties did exist in the database before, writing this object back will delete them.

So the proper solution is to map all the properties from the JSON structure into the Java class:

public static class DinosaurFacts {
    long appeared, vanished;
    double height, length, weight;
    String order;

    public long getAppeared() {
        return appeared;
    }

    public long getVanished() {
        return vanished;
    }

    public double getHeight() {
        return height;
    }

    public double getLength() {
        return length;
    }

    public double getWeight() {
        return weight;
    }

    public String getOrder() {
        return order;
    }
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Awesome it works now!! Did I miss this in the documentation anywhere? – Sonu Bhangoo Dec 12 '15 at 22:49
  • I'm not sure. The docs definitely mention that you must match each property in the JSON with a field in Java (hint: I wrote that part). But it doesn't explain tricks like `@JsonIgnoreProperties`. Use the link I provided in the comment to the question for that. – Frank van Puffelen Dec 13 '15 at 03:49