Moshi:Room 实体的通用 Json 转换器
Moshi : Generic Json converter for Room entity
我正在尝试使用 Moshi 创建一个通用的 JSON 解析器字符串到对象,但我不确定我是否做对了,因为我陷入了需要处理列表的场景中。
这个接口的想法是它可以用 Gson 或 Moshi 解析器实现
interface JsonParser {
fun <T> fromJson(jsonString: String, type: Class<T>): T?
fun <T> toJson(obj: T, type: Class<T>): String?
}
示例 Moshi 解析器
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)
}
}
示例转换器class
@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
那样做,在 Moshi 中,我们可以根据文档使用具体化扩展,但在这种情况下我不能这样做。
// We can just use a reified extension!
val adapter = moshi.adapter<List<Card>>()
样本数据class
@Parcelize
data class MetricsDomain(
val riskMetricsDomain: RiskMetricsDomain = RiskMetricsDomain(),
val roiByYearDomain: RoiByYearDomain = RoiByYearDomain(),
val roiDataDomain: RoiDataDomain = RoiDataDomain(),
val supplyDomain: SupplyDomain = SupplyDomain()
) : Parcelable
只需将这 2 个函数放入 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)
}
由于@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
注释中 class
@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
}
我正在尝试使用 Moshi 创建一个通用的 JSON 解析器字符串到对象,但我不确定我是否做对了,因为我陷入了需要处理列表的场景中。
这个接口的想法是它可以用 Gson 或 Moshi 解析器实现
interface JsonParser {
fun <T> fromJson(jsonString: String, type: Class<T>): T?
fun <T> toJson(obj: T, type: Class<T>): String?
}
示例 Moshi 解析器
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)
}
}
示例转换器class
@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
那样做,在 Moshi 中,我们可以根据文档使用具体化扩展,但在这种情况下我不能这样做。
// We can just use a reified extension!
val adapter = moshi.adapter<List<Card>>()
样本数据class
@Parcelize
data class MetricsDomain(
val riskMetricsDomain: RiskMetricsDomain = RiskMetricsDomain(),
val roiByYearDomain: RoiByYearDomain = RoiByYearDomain(),
val roiDataDomain: RoiDataDomain = RoiDataDomain(),
val supplyDomain: SupplyDomain = SupplyDomain()
) : Parcelable
只需将这 2 个函数放入 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)
}
由于@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
注释中 class
@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
}