Google Cloud Functions - 实时数据库触发器 - 如何将数据 JSON 反序列化为 POJO?

Google Cloud Functions - Realtime Database Trigger - how to deserialize data JSON to POJO?

如 Google 云函数 docs 中所述,可以根据 Firebase 实时数据库事件 (write/create/update/delete) 触发函数。

以下文档 sample 解释了如何获取 delta 快照。

public class FirebaseRtdb implements RawBackgroundFunction {
  private static final Logger logger = Logger.getLogger(FirebaseRtdb.class.getName());

  // Use GSON (https://github.com/google/gson) to parse JSON content.
  private static final Gson gson = new Gson();

  @Override
  public void accept(String json, Context context) {
    logger.info("Function triggered by change to: " + context.resource());

    JsonObject body = gson.fromJson(json, JsonObject.class);

    boolean isAdmin = false;
    if (body != null && body.has("auth")) {
      JsonObject authObj = body.getAsJsonObject("auth");
      isAdmin = authObj.has("admin") && authObj.get("admin").getAsBoolean();
    }

    logger.info("Admin?: " + isAdmin);

    if (body != null && body.has("delta")) {
      logger.info("Delta:");
      logger.info(body.get("delta").toString());
    }
  }
}

示例完美运行,但问题是:如何将此增量反序列化为 POJO?

我试过了:

val mObject = gson.fromJson(body.get("delta").toString(), MyCustomObject::class.java)

但我得到:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT

据我所知,这是因为 MyObject class 有一个 List<T> 字段,而 Firebase 数据库总是将列表转换为具有整数键的地图。

我最好不要将每个 List<T> 更改为 Map<Int,T>,因为我有很多 classes :(

提前致谢!

所以,这就是我最终所做的 (可能不是最好的解决方案!)

1) 为 Firebase 即将到来的列表创建自定义 Json 反序列化器:

class ListFirebaseDeserializer<T> : JsonDeserializer<ArrayList<T>> {
    override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): ArrayList<T> {
        val result = ArrayList<T>()
        val typeOfElement = (typeOfT as ParameterizedType).actualTypeArguments[0]

        json?.let {
            json.asJsonObject.entrySet().forEach {
                entry->
                result.add(Gson().fromJson(entry.value, typeOfElement))
            }
        }
        return result
    }
}

这会将 Firebase 转换为地图的列表并将其转换回实际列表。

2)@JsonAdapter(ListFirebaseDeserializer::class) 注释我的 POJO 中的每个列表,例如:

class MyCustomObject {

    @JsonAdapter(ListFirebaseDeserializer::class)
    var myPaymentList = ArrayList<Payment>()
}

如果您已经有很多列表要注释,这可能会很痛苦,但这比必须使用地图更好。

希望对您有所帮助!