Android 如何在 firebase 9.2 中使用自动值
How to use auto-value with firebase 9.2 in Android
我想使用 auto-value with firebase 9.2.0+。我有以下代码:
@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();
}
}
但是当我调用它时 Office office = childDataSnapshot.getValue(Office.class);
我收到了这个错误:
com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office
有人知道我为什么会收到此错误以及如何解决吗?我读到 firebase 不再使用 jackson
进行 json 序列化。所以我不确定如何指定一种 @JsonProperty("latitud")
我已经使用 @PropertyName
失败了。
我还尝试重命名抽象方法,如 public abstract double getLatitud();
,之后错误是下一个:
java.lang.InstantiationException: Can't instantiate abstract class com.example.app.model.Office
所以我不确定如何解决这个问题。
解决方案
感谢 hatboysam 和 Frank van Puffelen 我终于可以用下一个解决方案来解决这个问题了。
- 我根据 hatboysam 答案和 Frank van Puffelen[=53= 创建了一个 FirebaseUtil enum,其中包含两种序列化和反序列化 Firebase 对象的方法] 评论。
- 我创建了几个
User
和 Phone
类 用于测试。
依赖关系:
compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.0'
compile 'com.fasterxml.jackson.core:jackson-databind:2.8.0'
用法示例:
User user = FirebaseUtil.deserialize(dataSnapshot, User.class);
Map<String, Object> map = FirebaseUtil.serialize(user);
我不确定默认的 Firebase 数据映射器是否可行,但有一个可能的解决方法。首先让我们解释一下您看到的错误:
com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office
Firebase 映射器查找 public
字段或以 getFoo
/setFoo
模式命名的字段。因此,在您的 class 上,映射器看不到任何属性。
java.lang.InstantiationException: Can't instantiate abstract class com.example.app.model.Office
我认为这就是您出行时遇到的麻烦。为了使反序列化工作,您的 class 需要有一个 public,映射器可以通过反射调用的无参数构造函数 (newInstance()
)。据我所知,这不是 AutoValue 的工作方式。
但不要失去希望!。根据 this github issue,有一种方法可以使用 @JsonCreator
注释使 Jackson 和 AutoValue 兼容。因此,您需要同时使用 Jackson 和 Firebase 来完成这里的工作。
序列化:
// 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);
反序列化:
// 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);
我为此写了一个 AutoValue
扩展:
https://github.com/mattlogan/auto-value-firebase
该扩展生成一个与 firebase 兼容的 class,称为 FirebaseValue
,作为您生成的 AutoValue class 中的静态内部 class。您可以通过生成的构造函数在 AutoValue
class 和 FirebaseValue
class 之间进行转换。
这是从自述文件中复制的示例:
@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();
}
我想使用 auto-value with firebase 9.2.0+。我有以下代码:
@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();
}
}
但是当我调用它时 Office office = childDataSnapshot.getValue(Office.class);
我收到了这个错误:
com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office
有人知道我为什么会收到此错误以及如何解决吗?我读到 firebase 不再使用 jackson
进行 json 序列化。所以我不确定如何指定一种 @JsonProperty("latitud")
我已经使用 @PropertyName
失败了。
我还尝试重命名抽象方法,如 public abstract double getLatitud();
,之后错误是下一个:
java.lang.InstantiationException: Can't instantiate abstract class com.example.app.model.Office
所以我不确定如何解决这个问题。
解决方案
感谢 hatboysam 和 Frank van Puffelen 我终于可以用下一个解决方案来解决这个问题了。
- 我根据 hatboysam 答案和 Frank van Puffelen[=53= 创建了一个 FirebaseUtil enum,其中包含两种序列化和反序列化 Firebase 对象的方法] 评论。
- 我创建了几个
User
和Phone
类 用于测试。 依赖关系:
compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.0' compile 'com.fasterxml.jackson.core:jackson-databind:2.8.0'
用法示例:
User user = FirebaseUtil.deserialize(dataSnapshot, User.class); Map<String, Object> map = FirebaseUtil.serialize(user);
我不确定默认的 Firebase 数据映射器是否可行,但有一个可能的解决方法。首先让我们解释一下您看到的错误:
com.google.firebase.database.DatabaseException: No properties to serialize found on class com.example.app.model.Office
Firebase 映射器查找 public
字段或以 getFoo
/setFoo
模式命名的字段。因此,在您的 class 上,映射器看不到任何属性。
java.lang.InstantiationException: Can't instantiate abstract class com.example.app.model.Office
我认为这就是您出行时遇到的麻烦。为了使反序列化工作,您的 class 需要有一个 public,映射器可以通过反射调用的无参数构造函数 (newInstance()
)。据我所知,这不是 AutoValue 的工作方式。
但不要失去希望!。根据 this github issue,有一种方法可以使用 @JsonCreator
注释使 Jackson 和 AutoValue 兼容。因此,您需要同时使用 Jackson 和 Firebase 来完成这里的工作。
序列化:
// 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);
反序列化:
// 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);
我为此写了一个 AutoValue
扩展:
https://github.com/mattlogan/auto-value-firebase
该扩展生成一个与 firebase 兼容的 class,称为 FirebaseValue
,作为您生成的 AutoValue class 中的静态内部 class。您可以通过生成的构造函数在 AutoValue
class 和 FirebaseValue
class 之间进行转换。
这是从自述文件中复制的示例:
@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();
}