gson 莫希:Room实体的通用Json转换器

v7pvogib  于 2022-11-06  发布在  其他
关注(0)|答案(2)|浏览(173)

我试图用莫希创建一个通用的JSON解析器String to Object,但我不确定我是否做对了,因为我陷入了一个需要处理List的场景。
这个接口的思想是,它可以用Gson或莫希解析器实现

interface JsonParser {

    fun <T> fromJson(jsonString: String, type: Class<T>): T?

    fun <T> toJson(obj: T, type: Class<T>): String?

}

莫希剖析器范例

class MoshiParser(private val moshi: Moshi) : JsonParser {

    override fun <T> fromJson(jsonString: String, type: Class<T>): T? {
        return moshi.adapter(type).fromJson(jsonString)
    }

    override fun <T> toJson(obj: T, type: Class<T>): String? {
        return moshi.adapter(type).toJson(obj)
    }

}

示例转换器类

@ProvidedTypeConverter
    class JsonConverter(private val jsonParser: JsonParser) {

        @TypeConverter
        fun fromMetricsJson(jsonString: String): MetricsDomain {
            return jsonParser.fromJson(jsonString, MetricsDomain::class.java)
                ?: MetricsDomain() // Empty
        }

        @TypeConverter
        fun toMetricsJson(obj: MetricsDomain): String {
            return jsonParser.toJson(obj, MetricsDomain::class.java)
                ?: DEFAULT_VALUE_STRING // Empty
        }

    }

但是我怎么能处理像List这样的东西呢?

@TypeConverter
    fun fromHistoricalValuesJson(jsonString: String): List<List<Double>> {
        return jsonParser.fromJson(jsonString, // How to do this in Moshi)
            ?: emptyList()
    }

在Gson中,我认为我们可以像object : TypeToken<ArrayList<List<Double>>>(){}.type那样做,在莫希中,我们可以根据文档使用物化扩展,但在这种情况下我不能这样做。

// We can just use a reified extension!
val adapter = moshi.adapter<List<Card>>()

示例数据类

@Parcelize
data class MetricsDomain(
    val riskMetricsDomain: RiskMetricsDomain = RiskMetricsDomain(),
    val roiByYearDomain: RoiByYearDomain = RoiByYearDomain(),
    val roiDataDomain: RoiDataDomain = RoiDataDomain(),
    val supplyDomain: SupplyDomain = SupplyDomain()
) : Parcelable
5kgi1eie

5kgi1eie1#

只需将这两个函数放入一个Kotlin文件中:

val moshi: Moshi = Moshi
    .Builder()
    .add(KotlinJsonAdapterFactory())
    .build()    

inline fun <reified T> convertJsonToObject(json: String): T = 
    moshi.adapter(T::class.java).fromJson(json)

inline fun <reified T> convertObjectToJson(objectData: T): String =
    moshi.adapter(T::class.java).toJson(objectData)

并在转换器中使用:

class ObjectTypeConverter {

    @TypeConverter
    fun objectToString(myObj: MyObject): String = convertObjectToJson(myObj)

    @TypeConverter
    fun stringToObject(myObjStr: String): MyObject = convertJsonToObject(myObjStr)
}
gxwragnw

gxwragnw2#

多亏了@Eric注解,我们才能使用泛型类型来完成它。

class MoshiParser(private val moshi: Moshi) : JsonParser {

    override fun <T> fromJson(jsonString: String, type: Type): T? {
        return moshi.adapter<T>(type).fromJson(jsonString)
    }

    override fun <T> toJson(obj: T, type: Type): String? {
        return moshi.adapter<T>(type).toJson(obj)
    }

}

在您的@ProvidedTypeConverter注解类中

@TypeConverter
    fun fromListDoubleValuesJson(jsonString: String): List<List<Double>> {
        return jsonParser.fromJson(
            jsonString,
            Types.newParameterizedType(
                List::class.java,
                Types.newParameterizedType(List::class.java, Double::class.javaObjectType)
            )
        )
            ?: emptyList()
    }

    @TypeConverter
    fun toListDoubleValuesJson(obj: List<List<Double>>): String {
        return jsonParser.toJson(
            obj,
            Types.newParameterizedType(
                List::class.java,
                Types.newParameterizedType(List::class.java, Double::class.javaObjectType)
            )
        )
            ?: DEFAULT_VALUE_STRING
    }

相关问题