首页 > 解决方案 > 从 Firebase Firestore 检索 JSON 字符串

问题描述

我正在开发一个使用 Firebase Firestore 作为数据库的 android 应用程序。我正在尝试存储 SoldItems 列表,其中每个 soldItem 都有一个由 Sealed 类形成的 PrescriptionType。

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

定义为字符串的处方类型最初是密封类处方类型

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()}

由于 FirebaseFirestore android SDK 缺乏对密封类的直接支持,我将处方类型存储为字符串。我不得不创建自己的 TypeConverter。这在从每个处方类型生成字符串 (JSON) 以及从字符串生成处方类型方面非常有效。

@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)
    }
}

将字符串存储在数据库中效果很好。对象被存储,一切都很好——我们可以看到处方类型是一个字符串。

在 Firebase Firestore 中查看

但是,在 Firebase 中检索 soldItems 时,我们遇到了一个问题,即 firebase SDK 似乎返回 JSON 字符串并将其转换为对象,因此由于处方类型是字符串而不是对象而崩溃。

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}]

并尝试使用 Gson 创建 soldItems 会出错

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

我认为 Gson 想将处方类型解析为字符串,但看到的是一个对象。我试图用额外的引号填充处方类型字符串,但它仍然不起作用。

有谁知道我如何将处方类型检索为字符串?

标签: androidfirebasekotlingoogle-cloud-firestoregson

解决方案


推荐阅读