@@ -20,6 +20,19 @@ import org.jetbrains.ktor.benchmarks.Constants.WORLD_QUERY
2020import java.sql.Connection
2121import java.util.concurrent.ThreadLocalRandom
2222import kotlin.random.Random
23+ import kotlinx.serialization.Contextual
24+ import kotlinx.serialization.modules.SerializersModule
25+ import kotlinx.serialization.modules.contextual
26+ import kotlinx.serialization.modules.polymorphic
27+ import kotlinx.serialization.modules.subclass
28+ import kotlinx.serialization.KSerializer
29+ import kotlinx.serialization.descriptors.SerialDescriptor
30+ import kotlinx.serialization.descriptors.buildClassSerialDescriptor
31+ import kotlinx.serialization.descriptors.element
32+ import kotlinx.serialization.encoding.Decoder
33+ import kotlinx.serialization.encoding.Encoder
34+ import kotlinx.serialization.encoding.encodeStructure
35+ import kotlinx.serialization.encoding.decodeStructure
2336
2437@Serializable
2538data class Message (val message : String )
@@ -30,6 +43,65 @@ data class World(val id: Int, var randomNumber: Int)
3043@Serializable
3144data class Fortune (val id : Int , var message : String )
3245
46+ @Serializable
47+ data class DynamicValue (
48+ @Contextual
49+ val value : Any
50+ )
51+
52+ class AnySerializer : KSerializer <Any > {
53+ override val descriptor: SerialDescriptor = buildClassSerialDescriptor(" Any" ) {
54+ element<String >(" type" )
55+ element<String >(" value" )
56+ }
57+
58+ override fun serialize (encoder : Encoder , value : Any ) {
59+ encoder.encodeStructure(descriptor) {
60+ when (value) {
61+ is String -> {
62+ encodeStringElement(descriptor, 0 , " string" )
63+ encodeStringElement(descriptor, 1 , value)
64+ }
65+ is Number -> {
66+ encodeStringElement(descriptor, 0 , " number" )
67+ encodeStringElement(descriptor, 1 , value.toString())
68+ }
69+ is Boolean -> {
70+ encodeStringElement(descriptor, 0 , " boolean" )
71+ encodeStringElement(descriptor, 1 , value.toString())
72+ }
73+ is List <* > -> {
74+ encodeStringElement(descriptor, 0 , " list" )
75+ encodeStringElement(descriptor, 1 , json.encodeToString(value))
76+ }
77+ is Map <* , * > -> {
78+ encodeStringElement(descriptor, 0 , " map" )
79+ encodeStringElement(descriptor, 1 , json.encodeToString(value))
80+ }
81+ else -> {
82+ encodeStringElement(descriptor, 0 , " string" )
83+ encodeStringElement(descriptor, 1 , value.toString())
84+ }
85+ }
86+ }
87+ }
88+
89+ override fun deserialize (decoder : Decoder ): Any {
90+ return decoder.decodeStructure(descriptor) {
91+ val type = decodeStringElement(descriptor, 0 )
92+ val value = decodeStringElement(descriptor, 1 )
93+ when (type) {
94+ " string" -> value
95+ " number" -> value.toDoubleOrNull() ? : value
96+ " boolean" -> value.toBoolean()
97+ " list" -> json.decodeFromString<List <Any >>(value)
98+ " map" -> json.decodeFromString<Map <String , Any >>(value)
99+ else -> value
100+ }
101+ }
102+ }
103+ }
104+
33105// Optimized JSON instance with better performance settings
34106private val json = Json {
35107 prettyPrint = false
@@ -38,6 +110,17 @@ private val json = Json {
38110 coerceInputValues = true
39111}
40112
113+ // Create a custom JSON instance with the AnySerializer
114+ private val jsonWithAny = Json {
115+ serializersModule = SerializersModule {
116+ contextual(AnySerializer ())
117+ }
118+ prettyPrint = false
119+ isLenient = true
120+ ignoreUnknownKeys = true
121+ coerceInputValues = true
122+ }
123+
41124fun Application.main () {
42125 val dbRows = 10000
43126 val poolSize = Runtime .getRuntime().availableProcessors() * 2
@@ -160,6 +243,11 @@ fun Application.main() {
160243
161244 call.respondText(json.encodeToString(result), ContentType .Application .Json )
162245 }
246+
247+ post(" /dynamic-map" ) {
248+ val dynamicMap = call.receive<Map <String , DynamicValue >>()
249+ call.respondText(jsonWithAny.encodeToString(dynamicMap), ContentType .Application .Json )
250+ }
163251 }
164252}
165253
0 commit comments