Why do I get Failed to bounce to type when I turn JSON from Firebase into Java objects?
Firebase uses Jackson to allow serialization of Java objects to JSON and deserialization of JSON back into Java objects. You can find more about Jackson on the Jackson website and this page about Jackson annotations.
In the rest of this answer, we’ll show a few common ways of using Jackson with Firebase.
Loading complete users
The simplest way of loading the users from Firebase into Android is if we create a Java class that completely mimics the properties in the JSON:
private static class User {
String handle;
String name;
long stackId;
public String getHandle() { return handle; }
public String getName() { return name; }
public long getStackId() { return stackId; }
@Override
public String toString() { return "User{handle='"+handle+“', name='"+name+"', stackId="+stackId+"\’}”; }
}
We can use this class in a listener:
Firebase ref = new Firebase("https://stackoverflow.firebaseio.com/32108969/users");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot usersSnapshot) {
for (DataSnapshot userSnapshot : usersSnapshot.getChildren()) {
User user = userSnapshot.getValue(User.class);
System.out.println(user.toString());
}
}
@Override
public void onCancelled(FirebaseError firebaseError) { }
});
You may note that the User class follow the JavaBean property pattern. Every JSON property maps by a field in the User class and we have a public getter method for each field. By ensuring that all properties are mapped with the exact same name, we ensure that Jackson can automatically map them.
You can also manually control the mapping by putting Jackson annotations on your Java class, and its fields and methods. We’ll cover the two most common annotations (@JsonIgnore
and @JsonIgnoreProperties
) below.
Partially loading users
Say that you only care about the user’s name and handle in your Java code. Let’s remove the stackId
and see what happens:
private static class User {
String handle;
String name;
public String getHandle() { return handle; }
public String getName() { return name; }
@Override
public String toString() {
return "User{handle='" + handle + “\', name='" + name + "\’}”;
}
}
If we now attach the same listener as before and run the program, it will throw an exception:
Exception in thread "FirebaseEventTarget" com.firebase.client.FirebaseException: Failed to bounce to type
at com.firebase.client.DataSnapshot.getValue(DataSnapshot.java:187)
at com.firebase.LoadPartialUsers$1.onDataChange(LoadPartialUsers.java:16)
The “failed to debounce type” indicates that Jackson was unable to deserialize the JSON into a User object. In the nested exception it tells us why:
Caused by: com.shaded.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "stackId" (class com.firebase.LoadPartialUsers$User), not marked as ignorable (2 known properties: , "handle", "name"])
at [Source: java.io.StringReader@43079089; line: 1, column: 15] (through reference chain: com.firebase.User["stackId"])
at com.shaded.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:79)
Jackson found a property stackId
in the JSON and doesn’t know what to do with it, so it throws an exception. Luckily there is an annotation that we can use to tell it to ignore specific properties from the JSON when mapping it to our User
class:
@JsonIgnoreProperties({ "stackId" })
private static class User {
...
}
If we not run the code with our listener again, Jackson will know that it can ignore stackId
in the JSON and it will be able to deserialize the JSON into a User object again.
Since adding properties to the JSON is such a common practice in Firebase applications, you may find it more convenient to simply tell Jackson to ignore all properties that don’t have a mapping in the Java class:
@JsonIgnoreProperties(ignoreUnknown=true)
private static class User {
...
}
Now if we add properties to the JSON later, the Java code will still be able to load the User
s. Just keep in mind that the User objects won’t contain all information that was present in the JSON, so be careful when writing them back to Firebase again.
Partially saving users
One reason why it is nice to have a custom Java class, is that we can add convenience methods to it. Say that we add a convenience method that gets the name to display for a user:
private static class User {
String handle;
String name;
public String getHandle() { return handle; }
public String getName() { return name; }
@JsonIgnore
public String getDisplayName() {
return getName() + " (" + getHandle() + ")";
}
@Override
public String toString() {
return "User{handle='" + handle + "\', name='" + name + "\', displayName='" + getDisplayName() + "'}";
}
}
Now let's read the users from Firebase and write them back into a new location:
Firebase srcRef = new Firebase("https://stackoverflow.firebaseio.com/32108969/users");
final Firebase copyRef = new Firebase("https://stackoverflow.firebaseio.com/32108969/copiedusers");
srcRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot usersSnapshot) {
for (DataSnapshot userSnapshot : usersSnapshot.getChildren()) {
User user = userSnapshot.getValue(User.class);
copyRef.child(userSnapshot.getKey()).setValue(user);
}
}
@Override
public void onCancelled(FirebaseError firebaseError) { }
});
The JSON in the copiedusers
node looks like this:
"copiedusers": {
"-Jx5vuRqItEF-7kAgVWy": {
"displayName": "Frank van Puffelen (puf)",
"handle": "puf",
"name": "Frank van Puffelen"
},
"-Jx5w3IOHD2kRFFgkMbh": {
"displayName": "Kato Wulf (kato)",
"handle": "kato",
"name": "Kato Wulf"
},
"-Jx5x1VWs08Zc5S-0U4p": {
"displayName": "Jenny Tong (mimming)",
"handle": "mimming",
"name": "Jenny Tong"
}
}
That’s not the same as the source JSON, because Jackson recognizes the new getDisplayName()
method as a JavaBean getter and thus added a displayName
property to the JSON it outputs. We solve this problem by adding a JsonIgnore
annotation to getDisplayName()
.
@JsonIgnore
public String getDisplayName() {
return getName() + "(" + getHandle() + ")";
}
When serializing a User object, Jackson will now ignore the getDisplayName()
method and the JSON we write out will be the same as what we got it.
Failed to bounce to type. Trying upload a java object to Firebase realtime database
You are storing an instance of Driver
at location ref
. You are then adding a listener to that location and expecting to find children that are instances of Driver
. Instead just use the snapshot value: snapshot.getValue(Driver.class)
.
Or if you intend to have multiple drivers, add them with unique keys: ref.push().setValue(d)
. Then your listener logic to scan over the children will work.
If this is new development, you should also consider using the new Firebase SDK instead of the legacy SDK. Reference the Upgrade Guide.
Firebase failed to bounce to type when retrieving
The error is explicitly mention in the stack trace:
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "gab" (class Entity.Users), not marked as ignorable (7 known properties: , "address", "question", "userName", "password", "email", "answer", "phone"])
Since your JSON doesn't have a property called gab
, it seems like you're simply reading the data at the wrong level in your JSON tree.
The solution is to attach your listener one level lower in the tree on the Users
node:
Firebase ref = new Firebase(Config.FIREBASE_URL);
//Value event listener for realtime data update
ref.child("Users").addValueEventListener(new ValueEventListener() {
...
Getting 'Failed to bounce to type' exception even after giving the accurate firebase reference. Please see details
You've included a ImageView in your Java class, which Jackson/Firebase doesn't know how to serialize data to.
The solution is to tell Firebase/Jackson to ignore the ImageView when it reads the object from/writes it to JSON.
public class UsersDataFromFirebase {
private String userName;
private String userEmail;
private ImageView userImage;
public UsersDataFromFirebase() {
// empty default constructor, necessary for Firebase to be able to deserialize blog posts
}
public String getUserName() { return userName; }
public String getUserEmail() { return userEmail; }
@JsonIgnore
public ImageView getUserImage() { return userImage; }
}
Note that this is covered in my answer to this question: Why do I get "Failed to bounce to type" when I turn JSON from Firebase into Java objects?
What could be causing the failed bounce to type?
Try this,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Firebase.setAndroidContext(this);
Firebase ref = new Firebase("https://fbandg.firebaseio.com");
final TextView textbox = (TextView) findViewById(R.id.textbox);
ref.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
fObject fobject = new fObject();
fobject.setNewCondition(dataSnapshot.child("condition").getValue().toString());
textbox.setText(fobject.getNewCondition());
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
modify your fObject class,
public class fObject
{
String newCond;
public String getNewCond()
{
return newCond;
}
public void setNewCond(String cond)
{
newCond = cond;
}
}
Related Topics
How to Style the Progressbar Component in Javafx
How to Render a Pdf File in Android
How to Request Location Permission At Runtime
Java Using Much More Memory Than Heap Size (Or Size Correctly Docker Memory Limit)
How to Compare Strings in Java
Difference Between == and Equals() in Java
Convert a String Representation of a Hex Dump to a Byte Array Using Java
Why Don't Java'S +=, -=, *=, /= Compound Assignment Operators Require Casting
How to Handle Infinite Loop Caused by Invalid Input (Inputmismatchexception) Using Scanner
Why Is Subtracting These Two Times (In 1927) Giving a Strange Result
String Replace Method Is Not Replacing Characters
Difference Between Jsf, Servlet and Jsp
How to Set Environment Variables from Java
Java Logical Operator Short-Circuiting
:: (Double Colon) Operator in Java 8
Sending Http Post Request in Java