How to use auto-value with firebase 9.2 in Android

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 call this Office office = childDataSnapshot.getValue(Office.class); I get this error:

 com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office 

Someone have an idea why I get this error and how to solve it? I read that firebase no longer uses jackson to serialize json. So I'm not sure how to specify the type @JsonProperty("latitud") I used @PropertyName unsuccessfully.

I also tried to rename abstract methods such as public abstract double getLatitud(); , and after that the error is as follows:

 java.lang.InstantiationException: Can't instantiate abstract class com.example.app.model.Office 

So I'm not sure how to solve this.

Decision

Thanks hatboysam and Frank van Puffelen I finally ran into this problem with the following solution.

  • I created a FirebaseUtil enum with two methods for serializing and deserializing objects for Firebase based on the answer from hatboysam and Frank van Puffelen .
  • I am creating a couple of 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); 
+6
source share
2 answers

I'm not sure if this is possible by default mapping Firebase data, but there is a possible workaround. First explain the errors you see:

com.google.firebase.database.DatabaseException: no serialization properties found in com.example.app.model.Office class

The Firebase converter looks for either public fields or fields with a name with the pattern getFoo / setFoo . So, on your class mapper does not see any properties.

java.lang.InstantiationException: unable to instantiate abstract class com.example.app.model.Office

This is what I think you will have problems getting around. In order for deserialization to work, your class must have an open constructor without arguments, which can display the translator through reflection ( newInstance() ). As far as I know, this is not how AutoValue works.

But do not lose hope! . According to this github issue , there is a way to make compatibility with Jackson and AutoValue using the @JsonCreator annotation. Therefore, you will need to use both Jackson and Firebase to do this work here.

Serialization:

 // 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); 

deserialization:

 // 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); 
+4
source

I wrote an AutoValue extension for this:

https://github.com/mattlogan/auto-value-firebase

The extension creates a firebase-compatible class called FirebaseValue as a static inner class in your generated AutoValue class. You can convert between the AutoValue class and the FirebaseValue class through the generated constructors.

Here is an example copied from readme from what it looks like:

 @AutoValue @FirebaseValue public abstract class Taco { public static Taco create(String name, List<Ingredient> ingredients, Review review) { return new AutoValue_Taco(name, ingredients, review); } // Create AutoValue_Taco instance from AutoValue_Taco.FirebaseValue instance public static Taco create(DataSnapshot dataSnapshot) { AutoValue_Taco.FirebaseValue taco = dataSnapshot.getValue(AutoValue_Taco.FirebaseValue.class); return new AutoValue_Taco(taco); } // Create AutoValue_Taco.FirebaseValue instance from AutoValue_Taco instance public Object toFirebaseValue() { return new AutoValue_Taco.FirebaseValue(this); } public abstract String name(); public abstract List<Ingredient> ingredients(); public abstract Review review(); } 
0
source

All Articles