Using Moshi, I want to create generic adapter for enum that points to a class I want to use enum type because further down the elements i have complex structure which further boils to different types.
Is it possible to serialize this way via via Moshi?
I tried to make a generic adapter that can handle any type in Attempt
but so far I only have the clazz object not the actual T.
{
"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()
Take a look at PolymorphicJsonAdapterFactory which can be found in moshi-adapters artifact.
There's also moshi-sealed if you want avoid the boilerplate of manually writing a polymorphic adapter.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.