android - 使用 moshi 通过枚举序列化泛型
问题描述
背景
使用 Moshi,我想为枚举创建通用适配器,它指向我想使用枚举类型的类,因为在元素的更下方,我有复杂的结构,进一步归结为不同的类型。
是否可以通过 Moshi 以这种方式进行序列化?
我试图制作一个可以处理任何类型的通用适配器,Attempt
但到目前为止我只有 clazz 对象而不是实际的 T。
示例 Json
{
"items": [
{
"type": "A",
"apple": "123 Apples"
},
{
"type": "B",
"organge": "Banana 12",
"info": {}
},
{
"type": "C",
"grapes": "Green",
"quantity": {
"inStock": "12",
"offShelf": "12"
}
}
]
}
类结构
classs FruitResponse(val items: List<FruitTypes>)
@JsonClass(generateAdapter = false)
enum class FruitType(val clazz: Class<*>) {
A(Apple::class.java),
B(Banana::class.java),
C(Grapes::class.java)
}
试图
class FruitsAdapter<T : Enum<*>>(enumType: Class<T>) : JsonAdapter<T>() {
private val nameStrings: Array<String?>
private val nameConstantMap: MutableMap<String, T>
init {
try {
val constants = enumType.enumConstants
nameStrings = arrayOfNulls<String>(constants?.size ?: 0)
nameConstantMap = LinkedHashMap()
constants?.forEachIndexed { index, constant ->
val annotation = enumType.getField(constant.name).getAnnotation(Json::class.java)
val name = annotation?.name ?: constant.name
nameConstantMap[name] = constant
nameStrings[index] = name
}
} catch (e: NoSuchFieldException) {
throw AssertionError("Missing field in ${enumType.name}")
}
}
@Throws(IOException::class)
override fun fromJson(reader: JsonReader): T {
val name = reader.nextString()
val constant = nameConstantMap[name]
if (constant != null) return constant
throw JsonDataException(
"Expected one of ${Arrays.asList(*nameStrings)} " +
"but was $name at path ${reader.path}"
)
}
@Throws(IOException::class)
override fun toJson(writer: JsonWriter, value: T?) {
val newValue = nameConstantMap.filter { value == it.value }.map { it.key }.firstOrNull()
if (newValue != null) writer.value(newValue) else writer.nullValue()
}
}
// Usage
val moshiAdapter = Moshi.Builder()
.add(
FruitType::class.java,
FruitsAdapter(FruitType::class.java)
).build()
解决方案
看看PolymorphicJsonAdapterFactory可以在moshi-adapters工件中找到。
如果您想避免手动编写多态适配器的样板,还有moshi-sealed 。
推荐阅读
- asynchronous - Vuetify 滚动问题
- javascript - 在外部 js 文件上使用 $( document ).ready 时功能不起作用
- python-3.x - 执行 pytorch 代码 AttributeError 时出错:“函数”对象没有属性“变量”
- c# - Hangfire、.Net Core 和 Entity Framework:并发异常
- java - 遍历 DataProvider 的 JDBC ResultSet?
- scala - 在 if 保护之前转换 Scala 案例变量
- mysql - 通过结果MySQL的索引获取行的值
- python - 使用 Jinja2 的多个配置文件的 YAML 序列化数据
- css - bulma 的 `pagination-previous` 的源代码在哪里?
- c# - 使用证书解密加密密钥在 .NET 中不起作用但在 Openssql 中起作用