Извлечение строки JSON из Firebase Firestore

#android #firebase #kotlin #google-cloud-firestore #gson

#Android #firebase #kotlin #google-облако-firestore #gson

Вопрос:

Я работаю над приложением для Android, которое использует Firebase Firestore в качестве базы данных. Я пытаюсь сохранить список элементов SOLDITEM, где каждый элемент soldItem имеет PrescriptionType, сформированный из закрытых классов.

 data class SoldItem(var itemName : String = "",
                var quantity : String = "",
                var totalPrice : Int = 0,
                var itemQuantityType: ItemQuantityType = ItemQuantityType.SINGLE,
                var prescriptionType: String = ""
                ) : Serializable
  

prescriptionType, определенный как строка, изначально является закрытым классом PrescriptionType

 sealed class PrescriptionType : Parcelable {
// Check how to parcelize objects
@Parcelize
data class Syrup(var quantityInMls : Double = 2.5, var frequency : PrescriptionFrequency = PrescriptionFrequency.Stat, var time : PrescriptionTime = PrescriptionTime.OneDay) : PrescriptionType()

@Parcelize
data class Lotion(var frequency : PrescriptionFrequency = PrescriptionFrequency.Stat, var time : PrescriptionTime = PrescriptionTime.OneDay): PrescriptionType()

@Parcelize
data class Capsule(var quantity : Int = 1, var frequency : PrescriptionFrequency = PrescriptionFrequency.Stat, var time : PrescriptionTime = PrescriptionTime.OneDay ) : PrescriptionType()}
  

Я сохраняю prescriptionType в виде строки из-за отсутствия поддержки в FirebaseFirestore Android SDK непосредственно для закрытых классов. Мне пришлось создать свой собственный TypeConverter. Это довольно хорошо работает при генерации строки (JSON) из каждого prescriptionType, а также при генерации prescriptionType из строки.

 @JvmStatic
    @TypeConverter
    fun fromPrescription(prescriptionType: PrescriptionType) : String{
        val prescriptionAdapterFactory : RuntimeTypeAdapterFactory<PrescriptionType> = RuntimeTypeAdapterFactory.
                of(PrescriptionType::class.java, "type")
                .registerSubtype(PrescriptionType.Syrup::class.java, "Syrup")
                .registerSubtype(PrescriptionType.Lotion::class.java, "Lotion")
                .registerSubtype(PrescriptionType.Capsule::class.java, "Capsule")

        val gsonBuilder = GsonBuilder().registerTypeAdapterFactory(prescriptionAdapterFactory).create()
        return """  gsonBuilder.toJson(prescriptionType, PrescriptionType::class.java)   """
    }

    @JvmStatic
    @TypeConverter
    fun toPrescriptionType(prescriptionType : String) : PrescriptionType {
        val prescriptionAdapterFactory : RuntimeTypeAdapterFactory<PrescriptionType> = RuntimeTypeAdapterFactory.
                of(PrescriptionType::class.java, "type")
                .registerSubtype(PrescriptionType.Syrup::class.java, "Syrup")
                .registerSubtype(PrescriptionType.Lotion::class.java, "Lotion")
                .registerSubtype(PrescriptionType.Capsule::class.java, "Capsule")

        val gsonBuilder = GsonBuilder().registerTypeAdapterFactory(prescriptionAdapterFactory).create()
        return gsonBuilder.fromJson(prescriptionType, PrescriptionType::class.java)
    }
}
  

Сохранение строки в базе данных работает довольно хорошо. Объект сохранен, и все в порядке — мы видим, что prescriptionType представляет собой строку.

Просмотр в Firebase Firestore

Однако при извлечении soldItems в Firebase мы сталкиваемся с проблемой, когда кажется, что firebase SDK возвращает строку JSON и преобразует ее в объект и, следовательно, выходит из строя, поскольку prescriptionType — это строка, а не объект.

 val soldItemsType = object : TypeToken<List<SoldItem>>() {}.type
val soldItemsFromBackend = it.get("soldItems").toString()


Timber.d(soldItemsFromBackend)
val soldItems = Gson().fromJson<List<SoldItem>>(
                  soldItemsFromBackend,
                  soldItemsType
             )
  

Регистрация soldItemsFromBackend дает

 [{drugQuantityType=SINGLE, prescriptionType={"type":"Capsule","frequency":"Stat","quantity":1,"time":"OneDay"}, itemName=Docusate, quantity=2, totalPrice=0}]
  

и попытка создать soldItems с использованием Gson выдает ошибку

 Caused by: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 46 path $[0].prescriptionType
  

Я думаю, что Gson хочет проанализировать prescriptionType как строку, но вместо этого видит объект. Я пытался дополнить строку prescriptionType дополнительными кавычками, но это все равно не сработало.

Кто-нибудь, пожалуйста, знает, как я могу получить prescriptionType в виде строки?

Комментарии:

1. val soldItemsFromBackend = it.get("soldItems").toString() выглядит довольно сомнительно. В случае, если get(...) возвращает вам List , то вызов toString() для него вообще не дает действительного JSON. Таким образом, Firestore, скорее всего, правильно возвращает строку, но затем ваш toString() вызов вызывает String.toString() for prescriptionType , который просто опускает кавычки. Вместо этого вам, вероятно, следует выполнить итерацию по элементам SoldItem и применять Gson только к их prescriptionType строке JSON.

2. @Marcono1234, спасибо за ваш комментарий. it.get(…) фактически не возвращает список в этом экземпляре. Он возвращает тип Any?. Пожалуйста, вы знаете, как я могу получить soldItems в виде списка SoldItems?

3. Разве вы не можете просто привести ее, поскольку, по-видимому, во время выполнения это список? Кроме того, какой тип it имеет, или, скорее, какой метод it.get(...) ? Это com.google.firebase.firestore.Query.get(...) ?