v79
01/22/2023, 8:08 AMdata class ResponseEntity<T>(
val statusCode: Int,
val body: T? = null,
val headers: Map<String, String> = emptyMap(),
) {
companion object {
fun <T> ok(body: T? = null, headers: Map<String, String> = emptyMap()) =
ResponseEntity<T>(200, body, headers)
}
}
I absolutely, definitely need the KSerializationStrategy for T (if it exists, could be null), so that much later in the code, in another class, another method, I can call Json.encodeToString(entity.serializationStrategy, entity.body).
I think that I need to add another property to the ResponseEntity class, which stores the Class of T, or better still the KSerializer for T, or the KSerializationStrategy for T. But whatever combination of things I try - inline reified functions, typeOf(T) (which doesn't even compile) - I get stuck.v79
01/22/2023, 8:36 AM// call site
ResponseEntity.ok(body = SimpleClass("hello from simpleClass"), clazz = SimpleClass::class)
// ResponseEntity class
data class ResponseEntity<T : Any>(
val statusCode: Int,
val body: T? = null,
val headers: Map<String, String> = emptyMap(),
val clazz: KClass<T>? = null
) {
companion object {
fun <T : Any> ok(body: T? = null, headers: Map<String, String> = emptyMap(), clazz: KClass<T>? = null) =
ResponseEntity<T>(200, body, headers, clazz)
}
}
// eventually do the serialization in another class & method:
val kSerializer = responseEntity.clazz?.serializer()
val body: String = when (mimeType) {
MimeType.json -> {
kSerializer?.let {
Json.encodeToString(kSerializer,responseEntity.body as T)
} ?: "no-serializer"
}
//... etc
}
This is working. But it does require the user to to provide that clazz value, which I had hoped to avoid.v79
01/22/2023, 8:54 AMdata class ResponseEntity<T : Any>(
val statusCode: Int,
val body: T? = null,
val headers: Map<String, String> = emptyMap(),
) {
var clazz: KClass<T>? = null
companion object {
inline fun <reified T : Any> ok(body: T? = null, headers: Map<String, String> = emptyMap()): ResponseEntity<T> {
val tt = T::class
return ResponseEntity<T>(200, body, headers).apply { clazz = tt }
}
}
}Adam S
01/22/2023, 8:57 AMinline fun <reified T : Any> ResponseEntity(
statusCode: Int,
body: T? = null,
headers: Map<String, String> = emptyMap(),
) = ResponseEntity(statusCode, body, headers, T::class)ephemient
01/22/2023, 3:07 PM@Serializable
class Foo<T>(...)
creates a
Foo.serializer(tSerializer: KSerializer<T>): KSerializer<Foo<T>>
function on the companionephemient
01/22/2023, 3:09 PMclass ResponseEntitySerializer<T>(
private val tSerializer: KSerializer<T>
) : KSerializer<ResponseEntity<T>> {
...
}
@Serializable(with = ResponseEntitySerializer::class)
class ResponseEntity<T>(...)
has a ResponseEntity.serializer(tSerializer) just like the non-custom caseephemient
01/22/2023, 3:14 PMKClass for this purpose (type erasure) and you should not be carrying a serializer per instance either (that doesn't make much sense). instead, there should be some real call site that knows the real type that it is expectingv79
01/22/2023, 3:17 PMv79
01/22/2023, 9:03 PM