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