I want to use auto-value with firebase 9.2.0+. I have the following code:
@AutoValue
public abstract class Office {
public static Builder builder() {
return new AutoValue_Office.Builder();
}
public abstract double latitud();
public abstract double longitud();
@AutoValue.Builder
public static abstract class Builder {
public abstract Builder latitud(double latitud);
public abstract Builder longitud(double longitud);
public abstract Office build();
}
}
But when I make to call this Office office = childDataSnapshot.getValue(Office.class);
I am getting this error:
com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office
Somebody have an idea why I am getting this error and how to solve it? I read that firebase is no longer using jackson
for json serialization. So I am not sure how to specify a kind of @JsonProperty("latitud")
I have used @PropertyName
unsuccessfully.
I also tried rename the abstract methods like public abstract double getLatitud();
and after that the error is the next one:
java.lang.InstantiationException: Can't instantiate abstract class com.example.app.model.Office
So I am not sure how to solve this.
SOLUTION
Thanks to hatboysam and Frank van Puffelen I finally could face this problem with the next solution.
User
and Phone
classes for testing.Dependencies:
compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.0'
compile 'com.fasterxml.jackson.core:jackson-databind:2.8.0'
Usage example:
User user = FirebaseUtil.deserialize(dataSnapshot, User.class);
Map<String, Object> map = FirebaseUtil.serialize(user);
I'm not sure this is possible with the default Firebase data mapper, but there is a possible workaround. First let's explain the errors you're seeing:
com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office
The Firebase mapper looks for either public
fields or fields named with the getFoo
/setFoo
pattern. So on your class the mapper does not see any properties.
java.lang.InstantiationException: Can't instantiate abstract class com.example.app.model.Office
This is the one I think you'll have trouble getting around. In order for the deserialization to work your class needs to have a public, no-argument constructor that the mapper can call via reflection (newInstance()
). As far as I know this is not how AutoValue works.
But don't lose hope!. According to this github issue there is a way to make Jackson and AutoValue compatible using the @JsonCreator
annotation. So you'll need to use both Jackson and Firebase to get the job done here.
Serializing:
// Convert to a Map<String,Object> using Jackson and then pass that to Firebase
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = mapper.convertValue(office, Map.class);
databaseReference.setValue(map);
Deserializing:
// Use Firebase to convert to a Map<String,Object>
GenericTypeIndicator<Map<String,Object>> t = new GenericTypeIndicator<Map<String,Object>>() {};
Map<String,Object> map = dataSnap.getValue(t);
// Use Jackson to convert from a Map to an Office object
ObjectMapper mapper = new ObjectMapper();
Office pojo = mapper.convertValue(map, Office.class);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With