snowe
11/23/2021, 7:32 AM@Serializable
data class ChangeOrderInput(
val oldProposal: OldProposal,
val newProposals: List<NewProposal>
)
output:
@Serializable
data class ChangeOrderUnit(
val oldProposal: SingletonStore<OldProposal>,
val newProposals: ListDataStore<NewProposal>,
) : RuleUnitData
where ChangeOrderUnit
will always be deserialized from ChangeOrderInput
, never the other way around, and where SingletonStore/ListDataStores are created just by calling oldProposal.set()
or newProposals.add()
on the stores, with the element. e.g. the only difference between the objects are that the RuleUnit object has the objects contained in stores.snowe
11/23/2021, 7:34 AMconvertValue
method from Jackson. I'm not sure if I need to write a custom serializer or if there's someway I can force generic deserialization here.
It seems like I would need something like this:
object SingletonStoreSerializer : KSerializer<SingletonStore<*>> {
override val descriptor: SerialDescriptor = ChangeOrderUnit.serializer().descriptor
override fun serialize(encoder: Encoder, value: SingletonStore<*>) {
encoder.encodeSerializableValue(String.serializer(), value.toString())
}
override fun deserialize(decoder: Decoder): SingletonStore<*> {
val string = decoder.decodeString()
decoder.decodeStructure(descriptor) {
decodeNullableSerializableElement()
}
return Color(string.toInt(16))
}
}
but I can't figure out exactly what I need to do from the documentation. I don't really ever need to serialize the SingletonStore, I just need to deserialize it from either json or the ChangeOrderInput itself.Richard Gomez
11/23/2021, 12:51 PMI'm not sure if I need to write a custom serializerIn general, yes. 😄 I don't have any helpful suggestions, but for anyone else: here are the interfaces in question. Unless Tyler is using Drools instead. https://github.com/kiegroup/kogito-runtimes/blob/17f11e19b6e2c277a37c7edb64e7ffc7c[…]kogito-api/src/main/java/org/kie/kogito/rules/RuleUnitData.java https://github.com/kiegroup/kogito-runtimes/blob/49c622f08f3803d27d0585adfdeabe932[…]gito-api/src/main/java/org/kie/kogito/rules/SingletonStore.java https://github.com/kiegroup/kogito-runtimes/blob/49c622f08f3803d27d0585adfdeabe932[…]its/src/main/java/org/kie/kogito/rules/units/ListDataStore.java
snowe
11/23/2021, 3:56 PMephemient
11/23/2021, 6:20 PMephemient
11/23/2021, 6:21 PMsnowe
11/23/2021, 6:21 PMclass SingletonStoreSerializer<T>(private val dataSerializer: KSerializer<T>) : KSerializer<SingletonStore<T>> {
override val descriptor: SerialDescriptor = dataSerializer.descriptor
override fun serialize(encoder: Encoder, value: SingletonStore<T>) = dataSerializer.serialize(encoder, value.first())
override fun deserialize(decoder: Decoder) =
DataSource.createSingleton<T>().apply {
set(dataSerializer.deserialize(decoder))
}
}
class ListDataStoreSerializer<T>(private val dataSerializer: KSerializer<T>) : KSerializer<ListDataStore<T>> {
override val descriptor: SerialDescriptor = dataSerializer.descriptor
override fun serialize(encoder: Encoder, value: ListDataStore<T>) = dataSerializer.serialize(encoder, value.first())
override fun deserialize(decoder: Decoder) =
ListDataStore<T>().apply {
add(dataSerializer.deserialize(decoder)) // TODO this is wrong
}
}
snowe
11/23/2021, 6:24 PMephemient
11/23/2021, 6:25 PMprivate val surrogateSerializer = ListSerializer(dataSerializer)
override val descriptor: SerialDescriptor = surrogateSerializer.descriptor
override fun serialize(encoder: Encoder, value: ListDataStore<T>) {
encoder.encodeSerializableValue(surrogateSerializer, value.toList())
}
override fun deserialize(decoder: Decoder): ListDataStore<T> {
val list = decoder.decodeSerializableValue(surrogateSerializer)
return ListDataStore<T>().apply {
addAll(list)
}
}
snowe
11/23/2021, 6:26 PMsnowe
11/23/2021, 6:26 PMephemient
11/23/2021, 6:26 PMdataSerializer
is your "surrogate", that's fineephemient
11/23/2021, 6:27 PMKSerializer<List<T>>
, not KSerializer<T>
itselfsnowe
11/23/2021, 6:27 PMsnowe
11/23/2021, 6:27 PMsnowe
11/23/2021, 6:27 PMsnowe
11/23/2021, 6:28 PMclass ListDataStoreSerializer<T>(dataSerializer: KSerializer<T>) : KSerializer<ListDataStore<T>> {
private val surrogateSerializer = ListSerializer(dataSerializer)
override val descriptor: SerialDescriptor = surrogateSerializer.descriptor
override fun serialize(encoder: Encoder, value: ListDataStore<T>) {
encoder.encodeSerializableValue(surrogateSerializer, value.toList())
}
override fun deserialize(decoder: Decoder): ListDataStore<T> {
val list = decoder.decodeSerializableValue(surrogateSerializer)
return ListDataStore<T>().apply {
list.forEach { add(it) }
}
}
}
ephemient
11/23/2021, 6:29 PMephemient
11/23/2021, 6:29 PMephemient
11/23/2021, 6:33 PMdataSerializer: KSerializer<T>
doesn't (de)serialize a list, that's why surrogateSerializer: KSerializer<List<T>> = ListSerializer(dataSerializer)
is neededephemient
11/23/2021, 6:34 PMKSerializer<List<T>>
to a KSerializer<ListDataStore<T>>
ephemient
11/23/2021, 6:38 PMSingletonStoreSerializer
and ListDataStoreSerializer
are registered; easiest way will likely be
@file:UseSerializers(SingletonStoreSerializer::class, ListDataStoreSerializer::class)
at the top of the file that you define @Serializable class ChangeOrderUnit
in, that will cause its generated serializer to use those custom serializers for its propertiesephemient
11/23/2021, 6:42 PMChangeOrderUnit
which uses ChangeOrderInput.serializer()
as its surrogate. since it's your own type, you can register the serializer right there, e.g. @Serializable(with = ChangeOrderUnitSerializer::class) data class ChangeOrderUnit(...)
and it'll work for all usagessnowe
11/23/2021, 6:45 PM@Contextual
to register those serializers. is that incorrect?snowe
11/23/2021, 6:45 PM@Serializable
data class ChangeOrderUnit(
@Contextual val oldProposal: SingletonStore<OldProposal>,
@Contextual val newProposals: ListDataStore<NewProposal>,
) : RuleUnitData {
constructor() : this(
DataSource.createSingleton<OldProposal>(),
ListDataStore()
)
}
snowe
11/23/2021, 6:46 PMRuleUnitData
, but haven't figured that one out yet.snowe
11/23/2021, 6:47 PMephemient
11/23/2021, 6:50 PMephemient
11/23/2021, 6:51 PMsnowe
11/23/2021, 6:52 PM#FFFFFF
or r=255, g=255, b=255
etc?ephemient
11/23/2021, 6:54 PMval json = Json {
serializersModule = SerializersModule {
contextual(if (oldVersion) ColorAsHashSerializer else ColorAsTripletSerializer)
}
}
and change all @Contextual Color
throughout the whole treesnowe
11/23/2021, 6:58 PM@Contextual
as an annotation. Apparently kogito tries to read the annotation for some reason and fails. It looks like I am past those failures. Thank you for the help! I still have some stuff to figure out, it's not working yet, but this has gotten me much further than last night. 🎉 🙇🏽snowe
12/08/2021, 6:35 PMsnowe
12/08/2021, 6:35 PM2021-12-08 11:31:13,310 ERROR [io.qua.ama.lam.run.AbstractLambdaPollLoop] (Lambda Thread (DEVELOPMENT)) Failed to run lambda (DEVELOPMENT): kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 553: Expected start of the array '[', but had ':' instead
JSON input: ....."Standard"}]}},"oldPricePoint":{"type":"Monthly","id":"","pr.....
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
at kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:524)
at kotlinx.serialization.json.internal.AbstractJsonLexer.fail$kotlinx_serialization_json(AbstractJsonLexer.kt:221)
at kotlinx.serialization.json.internal.AbstractJsonLexer.unexpectedToken(AbstractJsonLexer.kt:204)
at kotlinx.serialization.json.internal.StringJsonLexer.consumeNextToken(StringJsonLexer.kt:74)
at kotlinx.serialization.json.internal.StreamingJsonDecoder.beginStructure(StreamingJsonDecoder.kt:41)
at kotlinx.serialization.internal.AbstractPolymorphicSerializer.deserialize(AbstractPolymorphicSerializer.kt:130)
at com.sunrun.pricing.changeorder.helpers.SingletonStoreSerializer.deserialize(Serialization.kt:29)
at com.sunrun.pricing.changeorder.helpers.SingletonStoreSerializer.deserialize(Serialization.kt:24)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36)
at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
at kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
at com.sunrun.pricing.changeorder.ChangeOrderUnit$$serializer.deserialize(ChangeOrderUnit.kt:17)
at com.sunrun.pricing.changeorder.ChangeOrderUnit$$serializer.deserialize(ChangeOrderUnit.kt:17)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:59)
at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36)
at kotlinx.serialization.json.Json.decodeFromString(Json.kt:100)
at com.sunrun.pricing.changeorder.ChangeOrderFnHandler$handleRequest$1.invoke(ChangeOrderFnHandler.kt:70)
at com.sunrun.pricing.changeorder.ChangeOrderFnHandler$handleRequest$1.invoke(ChangeOrderFnHandler.kt:26)
at com.sunrun.pricing.changeorder.helpers.serialization.RequestStreamWrapperKt.requestStreamWrapper(RequestStreamWrapper.kt:17)
at com.sunrun.pricing.changeorder.ChangeOrderFnHandler.handleRequest(ChangeOrderFnHandler.kt:26)
at io.quarkus.amazon.lambda.runtime.AmazonLambdaRecorder$1.processRequest(AmazonLambdaRecorder.java:183)
at io.quarkus.amazon.lambda.runtime.AbstractLambdaPollLoop$1.run(AbstractLambdaPollLoop.java:111)
at java.base/java.lang.Thread.run(Thread.java:829)
snowe
12/08/2021, 6:46 PM[
when deserializing the polymorphic type, though I don't understand why.
from kotlinx.serialization.json.internal.WriteMode
internal enum class WriteMode(@JvmField val begin: Char, @JvmField val end: Char) {
OBJ(BEGIN_OBJ, END_OBJ),
LIST(BEGIN_LIST, END_LIST),
MAP(BEGIN_OBJ, END_OBJ),
POLY_OBJ(BEGIN_LIST, END_LIST);
}
@OptIn(ExperimentalSerializationApi::class)
internal fun Json.switchMode(desc: SerialDescriptor): WriteMode =
when (desc.kind) {
is PolymorphicKind -> WriteMode.POLY_OBJ
StructureKind.LIST -> WriteMode.LIST
StructureKind.MAP -> selectMapMode(desc, { WriteMode.MAP }, { WriteMode.LIST })
else -> WriteMode.OBJ
}
why does PolymorphicKind
want to have a list handed to it? How can I force it to write with .OBJ
instead?snowe
12/08/2021, 9:24 PMjava.lang.IllegalArgumentException: Polymorphic value has not been read for class null
...snowe
12/08/2021, 10:32 PM