Adam Proschek
08/11/2023, 12:46 AMMenuGroup
that has a property that's a List<MenuGroup>
. When my custom initializer is first initialized, it attempts to create the descriptor
, which then recursively calls descriptor
again when it tries to register the element for that list property. Is there a way to get around this recursion that isn't a total hack?
Here's a stripped down version of the models, serializer, and json I'm trying to format to (yes, the json format is weird but it's an external requirement).
@Serializable(with = MenuGroupSerializer::class)
data class MenuGroup(
val id: String,
val name: String,
val menuItems: List<MenuItem>,
val menuGroups: List<MenuGroup>,
)
@Serializable
data class MenuItem(
val id: String,
val name: String,
val priceInCents: Int,
)
object MenuGroupSerializer: KSerializer<MenuGroup> {
override val descriptor = buildClassSerialDescriptor("MenuGroup") {
element<String>("name")
element<Map<String, MenuItem>?>("menuItems")
element<Map<String, MenuGroup>?>("menuGroups")
}
override fun deserialize(decoder: Decoder): MenuGroup {
TODO("Not yet implemented")
}
@OptIn(ExperimentalSerializationApi::class)
override fun serialize(encoder: Encoder, value: MenuGroup) {
encoder.encodeStructure(descriptor) {
encodeStringElement(
descriptor = descriptor,
index = 0,
value = value.name,
)
encodeNullableSerializableElement(
descriptor = descriptor,
index = 1,
serializer = MapSerializer(String.serializer(), MenuItem.serializer()),
value = value.menuItems.associateBy { it.name },
)
encodeNullableSerializableElement(
descriptor = descriptor,
index = 2,
serializer = MapSerializer(String.serializer(), MenuGroup.serializer()),
value = value.menuGroups.associateBy { it.name },
)
}
}
}
Desired output
{
"menuGroups": {
"Donuts": {
"menuGroups": {},
"menuItems": {
"Glazed": {
"priceInCents": 100
},
"Chocolate": {
"priceInCents": 100
}
},
},
"Drinks": {
"menuGroups": {},
"menuItems": {
"Coffee": {
"priceInCents": 100
},
"Tea": {
"priceInCents": 100
}
},
}
},
"menuItems": {}
}
Adam S
08/11/2023, 9:55 AMencoder.encodeStructure(descriptor) {
encodeStringElement(
descriptor = descriptor,
index = 0,
value = value.name,
)
Adam S
08/11/2023, 9:57 AM@Serializable
data class MenuGroupDelegate(
val name: String,
val menuItems: Map<String, MenuItemDelegate>,
val menuGroups: Map<String, MenuGroupDelegate>,
)
@Serializable
data class MenuGroupDelegate(
val priceInCents: Int,
)
Then KxS will auto-generate the descriptors, so you don't have to worry about the nitty gritty details.Adam Proschek
08/11/2023, 5:25 PM