6

我想在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

所以我不确定如何解决这个问题。

解决方案

感谢hatboysamFrank van Puffelen,我终于可以通过下一个解决方案来面对这个问题。

  1. 我基于hatboysam回答和Frank van Puffelen评论创建了一个FirebaseUtil 枚举,其中有两种方法用于序列化和反序列化 Firebase 的对象。
  2. 我创建了几个UserPhone类进行测试。
  3. 依赖项:

    compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.0'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.8.0'
    
  4. 使用示例:

    User user = FirebaseUtil.deserialize(dataSnapshot, User.class);
    Map<String, Object> map = FirebaseUtil.serialize(user);
    
4

2 回答 2

4

我不确定默认的 Firebase 数据映射器是否可以做到这一点,但有一种可能的解决方法。首先让我们解释一下您看到的错误:

com.google.firebase.database.DatabaseException:在类 com.example.app.model.Office 上找不到要序列化的属性

Firebase 映射器查找以/模式public命名的字段或字段。因此,在您的班级上,映射器看不到任何属性。getFoosetFoo

java.lang.InstantiationException:无法实例化抽象类 com.example.app.model.Office

这是我认为你会遇到麻烦的一个。为了使反序列化工作,您的类需要有一个公共的、无参数的构造函数,映射器可以通过反射 ( newInstance()) 调用该构造函数。据我所知,这不是 AutoValue 的工作方式。

但不要失去希望!. 根据这个 github 问题,有一种方法可以使用@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);
于 2016-07-08T14:59:12.903 回答
0

我为此写了一个AutoValue扩展:

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

该扩展生成一个与 firebase 兼容的类,称为FirebaseValue,作为您生成的 AutoValue 类中的静态内部类。您可以通过生成的构造函数在您的AutoValue类和您的类之间进行转换。FirebaseValue

这是一个从自述文件中复制的示例,其外观如下:

@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();
}
于 2016-08-13T16:50:06.290 回答