Моши создает json с динамическим внутренним классом данных

#android #kotlin #retrofit2 #moshi

Вопрос:

У меня есть moshi с дооснащением, и я хочу отправить динамический внутренний объект данных на серверную часть.

Допустим, мне нужно исправить некоторые данные на моей конечной точке:

 @PATCH("/animals/{animalId}/attributes")
suspend fun updateAnimal(@Path("animalId") animalId: String, @Body request: MyPetsRequest)
 

Но мой AnimalAttributes внутренний объект динамичен.

 @JsonClass(generateAdapter = true)
@Parcelize
data class MyPetsRequest(
    @Json(name = "name") val name: String,
    @Json(name = "attributes") val attributes: AnimalAttributes
) : Parcelable

interface AnimalAttributes : Parcelable // or sealed class possible when share same base fields

@JsonClass(generateAdapter = true)
@Parcelize
data class DogAttributes(
    @Json(name = "bark") val bark: Boolean,
    @Json(name = "bite") val bite: Boolean,
) : AnimalAttributes

@JsonClass(generateAdapter = true)
@Parcelize
data class CatAttributes(
    @Json(name = "weight") val weight: Int,
) : AnimalAttributes
 

Я попытался создать пользовательский адаптер для Moshi, но когда я использую @ToJson attributes данные внутреннего объекта, они экранируются (поэтому полный объект отправляется в качестве одного параметра).

 class AnimalAttributesAdapter {

    @ToJson
    fun toJson(value: AnimalAttributes): String {
        val moshi = Moshi.Builder().build()
        return when (value) {
            is DogAttributes -> moshi.adapter(DogAttributes::class.java).toJson(value)
            is CatAttributes -> moshi.adapter(CatAttributes::class.java).toJson(value)
            else -> throw UnsupportedOperationException("Unknown type to serialize object to json: $value")
        }
    }

    /**
     * Not supported, this object is used only one way to update data on server.
     */
    @FromJson
    fun fromJson(value: String): AnimalAttributes = throw UnsupportedOperationException()
}

Moshi.Builder().add(AnimalAttributesAdapter())
 

Результат в этом случае выглядит так:
{"name":"my pet name","attributes":"{"bark":"true", "bite":"false"}"}

Когда я пытаюсь использовать PolymorphicJsonAdapterFactory его, добавляется следующий параметр между атрибутами, что неприемлемо для моего варианта использования.

 PolymorphicJsonAdapterFactory.of(AnimalAttributes::class.java, "animal")
            .withSubtype(DogAttributes::class.java, "dog")
            .withSubtype(CatAttributes::class.java, "cat")
 

Результат в этом случае добавлен атрибут animal : {"name":"my pet name","attributes":{"animal":"dog","bark":true, "bite":false}}

I don’t need to deserialize object from json to data class. I only need create one way serialization to json.