# #kotlin #firebase-realtime-database #google-cloud-functions #gson
Вопрос:
Как описано в документах Google Cloud Functions, можно запускать функцию на основе событий базы данных Firebase в реальном времени (запись/создание/обновление/удаление).
В следующем примере документов объясняется, как получить дельта-снимок.
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 amp;amp; body.has("auth")) {
JsonObject authObj = body.getAsJsonObject("auth");
isAdmin = authObj.has("admin") amp;amp; authObj.get("admin").getAsBoolean();
}
logger.info("Admin?: " isAdmin);
if (body != null amp;amp; 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 имеет List<T>
поле, а база данных Firebase всегда преобразует списки в карты с целочисленными ключами.
Я предпочтительно не хочу менять каждый List<T>
на Map<Int,T>
, потому что у меня много занятий 🙁
Заранее спасибо!
Комментарии:
1. Пытаетесь прочитать данные в Android?
2. Нет, я читаю это в облачной функции (функция RawBackgroundFunction), как и в примере, но с использованием Kotlin.
Ответ №1:
Итак, вот что я в итоге сделал (возможно, не лучшее решение!):
1) Создайте пользовательский десериализатор Json для списков, входящих в Firebase:
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) Аннотируйте каждый список в моем POJO @JsonAdapter(ListFirebaseDeserializer::class)
, например:
class MyCustomObject {
@JsonAdapter(ListFirebaseDeserializer::class)
var myPaymentList = ArrayList<Payment>()
}
Это может быть неприятно, если у вас уже есть много списков для аннотирования, но это лучше, чем вместо этого использовать карты.
Надеюсь, это поможет!