Is there a way for me to grab the serializer or ev...
# serialization
s
Is there a way for me to grab the serializer or even just the type for all fields inside another serializable class? (I think the tl;dr is I wonder if I can go from a
SerialDescriptor
to get the right
KSerializer<>
. Or from a
KSerializer
, to grab the
KSerializer
of all the fields of that class. Say I got
Copy code
@Serializable
data class SomeSerializableDataClass(
  val firstNullableDate: LocalDate?,
  val secondNonNullDate: LocalDate,
  val someRandomField: String?,
  val aListOfSomethingElse: List<Foo>,
)
And I got passed inside an inline function, the reified type
T
which is
SomeSerializableDataClass
here so I can do
serializer<T>
for it and get back
KSerializer<SomeSerializableDataClass>
. Then inside there I'd like to in some way to know that I got
KSerializer<LocalDate?>
,
KSerializer<LocalDate>
,
KSerializer<String?>
,
KSerializer<List<Foo>>
, or even just get their real types so I can call
serializer<>()
on them?
My use case is that I am trying to make my life easier with https://medium.com/androiddevelopers/navigation-compose-meet-type-safety-e081fb3cf2f8 compose nav, to populate the NavTypes of each screen with the right types. I got this much going already https://github.com/HedvigInsurance/android/blob/a566e1dc8766fcbf2f62daf4fded34a00f[…]om/hedvig/android/navigation/compose/JsonSerializableNavType.kt Where for a destination I am doing this:
Copy code
@Serializable
  data class DateOfOccurrencePlusLocation(
    val dateOfOccurrence: LocalDate?,
    val maxDate: LocalDate,
    val selectedLocation: String?,
    val locationOptions: List<LocationOption>,
  ) : ClaimFlowDestination {
    companion object {
      val typeMap = mapOf(
        typePairOfNullable<LocalDate>(),
        typePairOf<LocalDate>(),
        typePairOf<List<LocationOption>>(),
      )
    }
  }
But I'd optimally like to be able to just do
Copy code
@Serializable
  data class DateOfOccurrencePlusLocation(
    val dateOfOccurrence: LocalDate?,
    val maxDate: LocalDate,
    val selectedLocation: String?,
    val locationOptions: List<LocationOption>,
  ) : ClaimFlowDestination {
    companion object {
      val typeMap = typeMapFor<DateOfOccurrencePlusLocation>()
    }
  }
And this
typeMapFor
I am hoping could potentially grab the right types using the metadata given by the serialization plugin and then I could hopefully do something along the lines of
Copy code
for (kclass in descriptor.elementsKclassList) {
  if (isNullable) {
    typePairOfNullable(kclass)
  } else {
    typePairOf(kclass)
  }
}
But from a SerialDescriptor I am not finding a way to grab the serializer of it, or the type of it.
Was hoping this would be it
Copy code
public val SerialDescriptor.capturedKClass: KClass<*>?
but I was wrong. The docs say "This property is null for descriptors that are not of SerialKind. CONTEXTUAL or PolymorphicKind. OPEN kinds"
Hmm I may be out of luck. The only thing I think the class serializer knows of those fields is their Descriptor. However, their descriptor does not necessarily seem to know anything about the class itself, but instead just what the serializer of that class has provided as a descriptor. For LocalDate for example this is just this https://github.com/Kotlin/kotlinx-datetime/blob/bc8adee2b9e3659e8e1c38fc09f3a4a1bdf85276/core/common/src/serializers/LocalDateSerializers.kt#L23-L24, a PrimitiveSerialDescriptor so I do not think it actually knows anything about the type itelf, nor of the outer KSerializer. As far as I can tell at least so far ☹️
e
yes. it is possible for multiple serializers to have the same descriptor
s
Yeap, that's also true. So from my (admittedly not so clear) description of what I wanna do, I probably can't do this right?
e
right. it's not possible from the outer serializer either
s
Any thoughts of alternatives I can take perhaps? Or is my best bet just doing some KSP thing to generate those for me?