java - studio - query firebase android
Cómo usar el valor automático con Firebase 9.2 en Android (2)
Escribí una extensión de AutoValue
para esto:
https://github.com/mattlogan/auto-value-firebase
La extensión genera una clase compatible con FirebaseValue
, llamada FirebaseValue
, como una clase interna estática en tu clase AutoValue generada. Puede convertir su clase AutoValue
y su clase FirebaseValue
través de los constructores generados.
Aquí hay un ejemplo, copiado del archivo Léame, de cómo se ve eso:
@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();
}
Quiero usar el valor automático con firebase 9.2.0+ . Tengo el siguiente código:
@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();
}
}
Pero cuando hago para llamar a esta Office office = childDataSnapshot.getValue(Office.class);
Estoy recibiendo este error:
com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office
¿Alguien tiene una idea de por qué estoy recibiendo este error y cómo resolverlo? Leí que firebase ya no usa jackson
para la serialización json. Así que no estoy seguro de cómo especificar un tipo de @JsonProperty("latitud")
He utilizado @PropertyName
sin éxito.
También intenté cambiar el nombre de los métodos abstractos como public abstract double getLatitud();
y después de eso, el error es el siguiente:
java.lang.InstantiationException: Can''t instantiate abstract class com.example.app.model.Office
Entonces no estoy seguro de cómo resolver esto.
SOLUCIÓN
Gracias a hatboysam y Frank van Puffelen finalmente pude enfrentar este problema con la próxima solución.
- Creé un enum de FirebaseUtil con dos métodos para serializar y deserializar objetos para Firebase basados en la respuesta de hatboysam y en el comentario de Frank van Puffelen .
- Creé un par de clases de
User
yPhone
para probar. Dependencias:
compile ''com.fasterxml.jackson.core:jackson-annotations:2.8.0'' compile ''com.fasterxml.jackson.core:jackson-databind:2.8.0''
Ejemplo de uso:
User user = FirebaseUtil.deserialize(dataSnapshot, User.class); Map<String, Object> map = FirebaseUtil.serialize(user);
No estoy seguro de que esto sea posible con el asignador de datos predeterminado de Firebase, pero existe una posible solución. Primero explique los errores que está viendo:
com.google.firebase.database.DatabaseException: no se han encontrado propiedades para serializar en la clase com.example.app.model.Office
El asignador de Firebase busca ya sea campos public
o campos nombrados con el patrón getFoo
/ setFoo
. Entonces, en su clase, el asignador no ve ninguna propiedad.
java.lang.InstantiationException: no se puede crear una instancia de la clase abstracta com.example.app.model.Office
Este es el que creo que tendrás problemas para moverte. Para que la deserialización funcione, su clase necesita tener un constructor público, sin argumentos, que el asignador pueda llamar mediante la reflexión ( newInstance()
). Hasta donde yo sé, esto no es así como funciona AutoValue.
¡Pero no pierdas la esperanza! . De acuerdo con este problema de github hay una manera de hacer que Jackson y AutoValue sean compatibles usando la anotación @JsonCreator
. Por lo tanto, deberá usar tanto Jackson como Firebase para realizar el trabajo aquí.
Serialización
// 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);
Deserializando:
// 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);