dimanche 17 octobre 2021

Serializing list of objects from class derived from kotlin interface using delegation

I'm new to Kotlin so I'm not sure I've taken the right approach, so any tips are welcome! I've implemented a MenuItem object using composition, delegation and the builder pattern following this excellent tutorial https://avwie.github.io/compositional-patterns-in-kotlin-part-1-delegation. My code is very similar to the final code block in the article.

My problem is now trying to serialize (and deserialize) the List of menuItems I've tried essentially everything I can google, using Jackson, Kotlinx and Gson without any success.

my MenuItem interface:

interface MenuItem {
    var id: Long
    var productName: String
    var description: String
    var productBasePrice: Float
    var onMenu: Boolean
    var productFinalPrice: Float

    fun findAll(): List<MenuItem?>
    fun findOne(id: Long): MenuItem?
    fun create(menuItem: MenuItem)
    fun update(menuItem: MenuItem)
    fun delete(menuItem: MenuItem)
    fun findByName(name: String): MenuItem?
    fun generateRandomId(): Long
}

we've got:

interface Food : MenuItem {
    var allergens: List<String>
}

implementation(note random values are just left in from debugging creation):


@Serializable
@Polymorphic
class FoodImpl(name: String, des: String, productBasePrice: Float, onMenu: Boolean, productFinalPrice: Float) : Food {
    override var allergens: List<String> = listOf<String>()
    override var id: Long = 2
    override var productName = name
    override var description: String = des
    override var productBasePrice: Float = 0f
    override var onMenu: Boolean = false
    override var productFinalPrice: Float = 0f
    override fun findAll(): List<MenuItem?> {
    // some methods left out

My builders:

class DishBuilder() : Builder<Dish> {
    var id: Long = 0
    var productName: String = ""
    var description = ""
    var productBasePrice = 0f
    var onMenu = false
    var productFinalPrice =0f
    var isStarter = false
    var isMain = true
    var isDesert = false
    var isOnBreakfast = false
    var isOnLunch = false
    var isOnDinner = true
    var isOnAllDay = false
//    var allergens = List<String>()

    override fun build(): Dish =
        Dish(CourseImpl(isStarter, isMain, isDesert),
            SittingImpl(isOnBreakfast, isOnLunch, isOnDinner, isOnAllDay),
            FoodImpl(productName, description, productBasePrice, onMenu, productFinalPrice ))
}

interface Builder<T> {
    fun build(): T
}

interface BuilderProvider<T, B : Builder<T>> {
    fun builder(): B
}

fun <T, B : Builder<T>> build(provider: BuilderProvider<T, B>, block: B.() -> Unit): T {
    val builder = provider.builder()
    block(builder)
    return builder.build()
}

build a Dish

class Dish(
    courseImpl: Course,
    sittingImpl: Sitting,
    foodImpl: Food
): MenuItem by foodImpl, Course by courseImpl, Sitting by sittingImpl {
    companion object : BuilderProvider<Dish, DishBuilder> {
        override fun builder(): DishBuilder = DishBuilder()
    }
}

The Course and Sitting interfaces:

interface Sitting {
    var isOnBreakfast: Boolean
    var isOnLunch: Boolean
    var isOnDinner: Boolean
    var isOnAllDay: Boolean
}

interface Course {
    var isStarter: Boolean
    var isMain: Boolean
    var isDesert: Boolean
}

I'm trying to serialize:

@Serializable
@Polymorphic var menuItems = mutableListOf<MenuItem>()

currently using:

var stri = Json.encodeToString(PolymorphicSerializer(MenuItem::class), menuItems)

I get error: Class 'Dish' is not registered for polymorphic serialization in the scope of 'Any'. Mark the base class as 'sealed' or register the serializer explicitly.

As mentioned, I've unsuccessfully tried a lot of different approaches, none of which I can get to work. Does anyone know what I could do? Thanks in advance

Aucun commentaire:

Enregistrer un commentaire